【问题标题】:Perl: Comparing two files and printing data that match and don't matchPerl:比较两个文件并打印匹配和不匹配的数据
【发布时间】:2012-09-05 08:20:07
【问题描述】:

对于下面的 Perl 代码,我需要提高其效率,因为处理输入文件(包含数百万行数据)需要花费数小时。关于如何加快速度的任何想法?

给定两个文件,我想比较数据并打印匹配的行和不匹配的行。请注意,两列需要互换比较。

例如,

input1.txt
A B
C D

input2.txt
B A
C D
E F
G H

请注意: 第 1 行和第 2 行匹配(可互换);第 3 行和第 4 行不匹配

Output:
B A match
C D match
E F don't match
G H don't match

Perl 代码:

#!/usr/bin/perl -w
use strict;
use warnings;

open INFH1, "<input1.txt" || die "Error\n";
open INFH2, "<input2.txt" || die "Error\n";
chomp (my @array=<INFH2>);

while (<INFH1>) 
{

  my @values = split;
  next if grep /\D/, @values or @values != 2;

  my $re = qr/\A$values[0]\s+$values[1]\z|\A$values[1]\s+$values[0]\z/;

    foreach my $temp (@array)
    {
    chomp $_;
    print "$_\n" if grep $_ =~ $re, $temp;                      
    }
}
close INFH1;
close INFH2;
1;

我们非常感谢有关如何提高此代码效率的任何想法。谢谢!

【问题讨论】:

    标签: regex arrays perl grep


    【解决方案1】:

    如果您有足够的内存,请使用哈希。如果符号在 input1.txt 中没有出现多次(即,如果 A B 在文件中,A X 不在),以下应该有效:

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my %hash;
    
    open my $F1, '<', 'input1.txt' or die $!;
    while (<$F1>) {
        my @values = split / /;
        @hash{@values} = reverse @values;
    }
    close $F1;
    
    open my $F2, '<', 'input2.txt' or die $!;
    while (<$F2>) {
        my @values = split / /;
        my $value = $hash{$values[0]};
        if ($value and $value eq $values[1]) {
            print "Matches: $_";
        } else {
            print "Does not match: $_";
        }
    }
    close $F2;
    

    更新:

    对于重复值,我会使用哈希值。只需对符号进行排序,第一个将是大哈希中的键,第二个将是子哈希中的键:

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my %hash;
    
    open my $IN1, '<', 'input1.txt' or die $!;
    while (<$IN1>) {
        my @values = sort split;
        undef $hash{$values[0]}{$values[1]};
    }
    close $IN1;
    
    open my $IN2, '<', 'input2.txt' or die $!;
    while (<$IN2>) {
        chomp;
        my @values = sort split;
        if (exists $hash{$values[0]}{$values[1]}) {
            print "$_ matches\n";
        } else {
            print "$_ doesn't match\n";
        }
    }
    close $IN2;
    

    【讨论】:

    • 由于文件非常大,可以安全地假设符号可能出现多次。
    • 对于重复值:如果仍然排序,为什么不比较排序后的数组?
    • 缩写:my @storage = map {[sort split]} &lt;$IN1&gt;; ... while (&lt;$IN2&gt;) { chomp; if(@{$storage[$.]} ~~ sort split) {
    • @Hachi:整洁。哈希查找应该更快,但我不确定没有基准测试。
    • @choroba:谢谢,更新后的代码非常有效地给出了正确的输出!
    【解决方案2】:

    对于那些对另一种独立于列数的解决方案感兴趣的人:

    #!/usr/bin/perl -w
    
    use strict;
    use warnings;
    use 5.010;
    
    open INFH1, "<", input1.txt" || die "Error\n";
    my @storage = map {[sort split]} <$IN1>; # store content as matrix (each row sorted)
    close INFH1;
    
    open INFH2, "<input2.txt" || die "Error\n";
    while(<INFH2>) {
        chomp;
        if(@{$storage[$.]} ~~ sort split) { # if stored matrix row is elementwise-equal to current line (each row sorted)
            say "$_ matches";
        }
        else {
            say "$_ doesn't match";
        }
    }
    close INFH2;
    

    【讨论】:

    • 我尝试使用示例输入运行此代码,但恐怕输出不正确。
    猜你喜欢
    • 1970-01-01
    • 2017-07-30
    • 2021-06-15
    • 2016-10-23
    • 1970-01-01
    • 2019-06-24
    • 2017-07-07
    • 1970-01-01
    • 2016-07-30
    相关资源
    最近更新 更多