4

以下のPerlコードの場合、入力ファイル(数百万行のデータを含む)の処理に数時間かかるため、効率を上げる必要があります。どうすればスピードアップできるかについてのアイデアはありますか?

2つのファイルがある場合、データを比較して、一致する行と一致しない行を出力します。2つの列を同じ意味で比較する必要があることに注意してください。

例えば、

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;

このコードの効率を上げる方法についてのアイデアは高く評価されています。ありがとう!

4

2 に答える 2

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;

アップデート:

繰り返される値には、ハッシュのハッシュを使用します。シンボルを並べ替えるだけで、最初のシンボルが大きなハッシュのキーになり、2番目のシンボルがサブハッシュのキーになります。

#!/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;
于 2012-09-12T10:31:53.003 に答える
0

列の数に依存しない別のソリューションに関心のある人のために:

#!/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;
于 2012-09-13T12:12:43.440 に答える