0

非常に多くの冗長レコードが存在する入力ファイルがあり、冗長性の一部を削除するプログラムを作成しようとしていますが、それでもある程度の冗長性が残っているようですが、何が問題なのかわかりません

ARGV[0]は冗長性のある入力ファイルです

ARGV [1]は、入力ファイルの冗長性のない出力ファイルです。

open(Input,"<./$ARGV[0]");
open(Output,">./$ARGV[1]");

while( eof(Input) !=1)
{
    push(@Records,readline(*Input));
}
close Input;

# Solution 2
for($i=0;$i<$#Records;$i++)
{
    for($j=$i+1;$j<$#Records;$j++)
    {
        if($Records[$i] eq $Records[$j])
        {
            $Records[$j] = undef;
        }
    }
}

@Records = grep defined,@Records;

=begin
# Solution 1 have some problems
for($i=0;$i<$#Records;$i++)
{
    for($j=$i+1;$j<$#Records;$j++)
    {
        if($Records[$i] eq $Records[$j])
        {
            splice @Records,$j,1;
            $j = $j-1;  
        }
    }
}
=end
=cut

foreach $Each(@Records)
{
    print Output $Each;
}
close Output;

ありがとう

4

3 に答える 3

2

これは、より現代的なソリューションです。

open(my $fh_input, '<', $ARGV[0]) or die $!;
open(my $fh_output, '>', $ARGV[1]) or die $!;
my %records = ();

while( my $line = <$fh_input> )
{
   $records{$line} = 1;
}

foreach my $record(keys %records)
{
    print $fh_output $record;
}

close $fh_input;
close $fh_output;

ご覧のとおり、重複を避けるためにハッシュを使用しました

于 2013-03-10T10:21:11.540 に答える
1

を簡単に使用できますuniq()

my @records;
while( eof(Input) !=1)
{
    push(@records,readline(*Input));
}
close Input;

@records = uniq(@records); ## Unique elements in @records

こちらのドキュメントをご覧ください。

于 2013-03-10T10:00:33.030 に答える
1

あなたの「解決策1」が最も近いです。配列要素を に設定しundefても削除されず、必要に応じて警告を有効にしている場合は警告メッセージが表示されます。

このソリューションは、インデックスで各レコードをチェックし、重複している場合$jはそれを削除するかsplice(比較する次のレコードが同じインデックスになるように残りのレコードをシャッフルします)、そのままにしてスキップします。増加します$j

$infhベアワード ファイル ハンドル ( など) ではなく、レキシカル ファイル ハンドル ( など) を使用することをお勧めしますInput。の 3 パラメーター形式も使用し、それが成功したかどうかopen常に確認する必要があります。ここでは、すべてを明示的にautodieチェックすることを避けてきました。いずれかの呼び出しが失敗openすると、例外がスローされます。open

use strict;
use warnings;
use autodie;

my ($infile, $outfile) = @ARGV;

my @records = do {
    open my $infh, '<', $infile;
    <$infh>;
};

for my $i (0..$#records-1) {
    my $j = $i + 1;
    while ($j < @records) {
        if ($records[$j] eq $records[$i]) {
            splice @records, $j, 1;
        }
        else {
            ++$j;
        }
    }
}

open my $outfh, '>', $outfile;
print $outfh $_ for @records;
close $outfh;

ハッシュを使用した代替ソリューションは次のようになります

use strict;
use warnings;
use autodie;

my ($infile, $outfile) = @ARGV;

open my $infh,  '<', $infile;
open my $outfh, '>', $outfile;

my %seen;

while (<$infh>) {
  print $outfh $_ unless $seen{$_}++;
}
于 2013-03-10T10:29:07.927 に答える