2014-01-17 3 views
3

Я импортирую CSV, который имеет 3 столбца, один из этих столбцов может иметь дубликаты записей.Поиск дубликатов значений столбцов в CSV

У меня есть 2 вещи, чтобы проверить:

1. The field 'NAME' is not null and is a string 
2. The field 'ID' is unique 

До сих пор я разбор файл CSV, один раз и проверяя, что 1. (NAME is valid), что если это не удается, он просто ломает из цикла в то время и останавливается ,

Я думаю, вопрос в том, как я проверил бы, что ID уникален?

У меня есть такие поля, как следующее:

NAME, ID, 
Bob, 1, 
Tom, 2, 
James, 1, 
Terry, 3, 
Joe, 4, 

Это будет выводить что-то вроде `Дублированный ID в строке 3'

Благодаря

PS это CSV файл имеет несколько столбцов и может иметь вокруг 100 000 записей. Я упростил его по определенной причине для решения Дубликат колонке/Поле

Благодаря

+0

Вы вставляете в db? – user1844933

+0

Как насчет нажатия каждого значения в массиве и проверки в каждой строке, что значение «ID» отсутствует в этом массиве?Тогда, если это так, просто ошибка «echo» в строке xxx »;' – Jerska

+1

Если вы проверите это на сайте кодирования, это может привести к проблемам с производительностью. Я думаю, лучший способ - проверить уровень ввода данных и построить CSV-состояние. Если вы не заботитесь о проблемах с производительностью, вы можете проверить, что ваш идентификатор уже существует или нет в вашем db или месте хранения на стороне программы. –

ответ

0

Я пошел предполагая определенный тип конструкции, как и раздели часть CSV, но идея остается той же:

<?php 
    /* Let's make an array of 100,000 rows (Be careful, you might run into memory issues with this, issues you won't have with a CSV read line by line)*/ 
    $arr = []; 
    for ($i = 0; $i < 100000; $i++) 
    $arr[] = [rand(0, 1000000), 'Hey']; 

    /* Now let's have fun */ 
    $ids = []; 
    foreach ($arr as $line => $couple) { 
    if ($ids[$couple[0]]) 
     echo "Id " . $couple[0] . " on line " . $line . " already used<br />"; 
    else 
     $ids[$couple[0]] = true; 
    } 
?> 

100, 000 строк не так много, этого будет достаточно. (Он работал через 3 секунды у меня.)

EDIT: Как указывалось, in_array менее эффективен, чем поиск ключей. Поэтому я обновил свой код.

0

Дайте ему попробовать:

$row = 1; 
    $totalIDs = array(); 
    if (($handle = fopen('/tmp/test1.csv', "r")) !== FALSE) 
    { 
     while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) 
     {       
      $name = ''; 

      if (isset($data[0]) && $data[0] != '') 
      { 
       $name = $data[0]; 
       if (is_numeric($data[0]) || !is_string($data[0])) 
        echo "Name is not a string for row $row\n"; 
      } 
      else 
      { 
       echo "Name not set for row $row\n";  
      } 

      $id = ''; 
      if (isset($data[1])) 
      { 
       $id = $data[1];     
      } 
      else 
      { 
       echo "ID not set for row $row\n";    
      } 

      if (isset($totalIDs[$id])) 
       echo "Duplicate ID on line $row\n"; 
      else      
       $totalIDs[$id] = 1;       

      $row++; 
     } 
     fclose($handle); 
    } 
0

ли идентификаторы отсортированный с возможными дубликатами между или они распределены случайным образом?

Если они отсортированы и в списке нет отверстий (1,2,3,4 в порядке, 1,3,4,7 НЕ ОК), то просто сохраните последний идентификатор, который вы читаете, и сравните его с текущий идентификатор. Если ток равен или меньше последнего, то это дубликат.

Если идентификаторы находятся в случайном порядке, вам придется хранить их в массиве. Здесь у вас несколько вариантов. Если у вас есть много памяти просто хранить идентификатор в качестве ключа в простом массиве PHP и проверить его:

$ids = array(); 
// ... read and parse CSV 
if (isset($ids[$newId])) { 
    // you have a duplicate 
} else { 
    $ids[$newId] = true; // new value, not a duplicate 
} 

PHP массивы являются хэш-таблицы и имеют очень быстрый просмотр ключа. Сохранение идентификаторов в качестве значений и поиск с помощью in_array() сильно повредят производительности при увеличении массива.

Если вам нужно сохранить память, и вы знаете количество строк, которые вы собираетесь читать из CSV, вы можете использовать SplFixedArray вместо простого PHP-массива. Повторная проверка будет такой же, как и выше.

+0

Они распределены случайным образом. –

1
<?php 
$cnt = 0; 
$arr=array(); 
if (($handle = fopen("1.csv", "r")) !== FALSE) { 
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { 
     $num=count($data); 
     $cnt++; 
     for ($c=0; $c < $num; $c++) { 
      if(is_numeric($data[$c])){ 
       if (array_key_exists($data[$c], $arr)) 
        $arrdup[] = "duplicate value at ".($cnt-1); 
       else 
        $arr[$data[$c]] = $data[$c-1]; 
      } 
     } 
    } 
    fclose($handle); 
} 
print_r($arrdup); 
Смежные вопросы