Skip to main content
 首页 » 编程设计

python之查找 CSV 行的最有效方法是什么,该行不包含该行字段中的重复条目(不包括空白条目)

2025年05月04日16powertoolsteam

我正在查找 CSV 文件中包含该行的两个或多个字段中重复数据的所有行(即查找每个字段中没有唯一数据的所有行。)

例如,我有以下 CSV 文件:

John,Smith,Smith,21 
Mary,Jones,Smith,32 
John,42,42,42 
Henry,Brown,Jones,31 
Mary,,,21 

我想要打印以下行:

John,Smith,Smith,21 
John,42,42,42 

打印这些行是因为这些行的一个字段中的数据出现在另一个字段中。请注意,即使“Mary,,,21”有重复的空白字段,也不会打印出来。

我可以编写一个 Python 脚本并记录每行中每个条目出现的次数,但似乎必须有更好的方法来做到这一点。

请您参考如下方法:

使用 perl :

perl -F, -lane 'my %s; print if grep { $s{$_}++ } @F' 

用途:

  • -F,将字段分隔符设置为 ,
  • -l自动处理换行
  • -a自动拆分
  • -n将其包装在 while ( <> ) { 中环形。
  • -e指定要执行的代码。

传入数据在 , 上自动拆分进入@F我们使用 %s散列以发现是否有骗局。

如果——根据您的评论——您需要跳过空白字段(这将被视为欺骗):

perl -F, -lane 'my %s; print if grep { /./ ? $s{$_}++ : () } @F' 

这包括用于测试字段是否为空的三元运算符。

使用 Windows 进行测试(由于引号的缘故,这并不完全相同):

C:\Users\me>perl -F, -lane "my %s; print qq{line matches:$_} if grep { /./ ? $s{$_}++ : () } @F" 
line matches:John,Smith,Smith,21 
line matches:John,42,42,42 

如果手写,它看起来更像这样:

#!/usr/bin/env perl 
use strict; 
use warnings; 
 
while ( my $line = <DATA> ) { 
   my %seen; 
   chomp($line);  
   my @fields = split /,/, $line;  
   if ( grep { /./ and $seen{$_}++ } @fields ) {  
       print $line,"\n"; 
   } 
} 
 
__DATA__ 
John,Smith,Smith,21 
Mary,Jones,Smith,32 
John,42,42,42 
Henry,Brown,Jones,31 
Mary,,,21 

您可以使用 Text::CSV模块来解析它,但我建议不要这样做,除非你专门处理引用/嵌入的换行符等。

例如:

#!/usr/bin/env perl 
use strict; 
use warnings; 
 
use Data::Dumper; 
use Text::CSV;  
 
my $csv = Text::CSV -> new ( {sep_char => ',', eol => "\n", binary => 1} );  
 
while ( my $row = $csv -> getline ( \*DATA ) ) { 
   my %seen;  
   if ( grep { /./ and $seen{$_}++ } @$row ) {  
       print join ",", @$row, "\n"; 
   } 
} 
 
__DATA__ 
John,Smith,Smith,21 
Mary,Jones,Smith,32 
John,42,42,42 
Henry,Brown,Jones,31 
Mary,,,21