Поиск повторяющихся значений столбцов в CSV



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



Мне нужно проверить 2 вещи:



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


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



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



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



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


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



Спасибо



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



Спасибо

719   4  

4 ответов:

Я пошел предполагая определенный тип дизайна, так как убрал 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 менее эффективен, чем поиск ключей. Поэтому я обновил свой код.

<?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);

Попробуйте:

    $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);
    }

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

Если они отсортированы и в списке нет дырок (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. Дубликат чека будет таким же, как и выше.

Comments

    Ничего не найдено.