在CSV中查找重复的列值

时间:2014-01-17 10:50:53

标签: php csv fgetcsv

我正在导入一个包含3列的CSV,其中一列可能有重复的记录。

我要检查两件事:

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,

这将输出类似“第3行的重复ID”

由于

P.S此CSV文件包含更多列,可以有大约100,000条记录。我已将其简化为特定原因以解决重复的列/字段

由于

4 个答案:

答案 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);

答案 1 :(得分: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秒钟。)

编辑:正如所指出的,in_array的效率低于密钥查找。我因此更新了我的代码。

答案 2 :(得分: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);
    }

答案 3 :(得分:0)

ID是否按可能重复的方式排序,或者是随机分布的?

如果它们已经排序并且列表中没有漏洞(1,2,3,4可以; 1,3,4,7不正常)那么只需存储您读取的最后一个ID并将其与当前ID。如果当前等于或小于最后,那么它就是重复。

如果ID是随机顺序,那么您必须将它们存储在一个数组中。你有多种选择。如果你有足够的内存,只需将ID存储为普通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数组是哈希表,并且具有非常快速的键查找。将ID存储为值并使用in_array()进行搜索会在阵列增长时损害性能。

如果必须保存内存,并且知道要从CSV读取的行数,则可以使用SplFixedArray而不是普通的PHP数组。重复检查将与上述相同。