2014-01-17 88 views
3

我正在导入具有3列的CSV,其中一列可能有重复的记录。在CSV中查找重复的列值

我有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'

感谢

PS这个CSV文件还有更多列,可以绕100,000条记录。我已经简化它的特殊原因,解决了重复的列/场

感谢

+0

你插入到数据库? – user1844933

+0

如何推送数组中的每个值并在每行检查“ID”值不在此数组中?那么如果是这样,只是'回声'xxx行上的错误“;' – Jerska

+1

如果你在编码站点检查这个,可能会发生性能问题。我认为,更好的方法是检查数据输入级别并建立CSV状态。如果不关心性能问题,您可以检查您的ID是否已存在或不在您的数据库或程序端的存储位置。 –

回答

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效率低于密钥查找。我已经更新了我的代码。

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

与可能的重复排序之间的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数组哈希表,有一个非常快速键查找。将数据存储为值并使用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);