0

いくつかの数字が上下に並んでいるファイルを読み取るための Perl スクリプトを作成しました。重複を取り除き、新しいリストをファイルに保存したい。これが私のスクリプトです:

use strict;

my $arg = "<abs path to>\\list.txt";
open (FH, "$arg") or die "\nError trying to open the file $arg : $!";
print "Opened File : $arg\n";
my $line = "";
my @lines = <FH>;
close FH;
my $temp;
my $count = 0;
my $check = 0;
my @list;
my $flag;

for $line (@lines)
{
    $count += 1;
    $check = $count;
    $flag = 1;
    for my $next (@lines)
    {
        $check -= 1;
        if($check < 0)
        {
            if ($line == $next)
            {
                $flag = 0;
            }
        }
    }

    if($flag == 1)
    {
        push (@list, $line);
    }
}

my $newarg = "<abs path to>\\new_list.txt";
open (FWH, ">>$newarg") or die "\nError trying to open the file $newarg for writing : $!";
my $size = @list;
print FWH "\n\n*** Size = $size ***\n\n";
for my $line (@list)
{
    print FWH "$line";
}

私はPerlを学ぼうとしているC++の男です。スクリプトのサイズを縮小した可能性のある Perl の API を教えてください。スクリプトを読みやすく、簡単に理解できるようにしたいので、間隔を空けます。ありがとうございました。

4

4 に答える 4

4

番号のファイルがあり、順序を維持しながら重複を削除したいですか? これは Perl のワンライナーです。

perl -ne 'print unless $seen{$_}++' file > newfile

または:

# saves original in file.bak
perl -i.bak -ne 'print unless $seen{$_}++' file

単一の数値以外を含む行がある場合、統計を出力したい場合、引数の処理を改善したい場合、またはこれが異なる空白を持つ数値を重複排除しないことに気付いた場合は、次に、これを適切に変更します。例えば:

# whitespace/non-numbers tolerant
perl -i.bak -ne 'if (/^\s*(\d+)\s*$/) { print unless $seen{$1}++ } else { print }'

スクリプトとして、主要なロジックはまったく同じです。

#! /usr/bin/env perl
use common::sense;
use autodie;

my $silent;
$silent = shift if (@ARGV > 0 and $ARGV[0] eq '-s');
die "usage: $0 [-s] src dest\n" unless @ARGV == 2;

open my $fi, '<', shift;
open my $fo, '>', shift;

my %seen;
while (<$fi>) {
  if (/^\s* (\d+) \s*$/x) {
    print {$fo} $_ unless $seen{$1}++;
    next;
  }
  print {$fo} $_;
}

unless ($silent) {
  say '-- de-dup stats --';
  say '-- $count $number --'
}
for (sort { $a <=> $b } keys %seen) {
  say "$seen{$_} $_"
}

編集:へえ、重複がすべて隣接している場合も考慮していませんでした。ここではハッシュは必要ありません:

perl -ne 'print unless $_ == $last; $last = $_' file > newfile
于 2013-05-28T14:40:57.863 に答える
3

何かを追跡する必要があるときはいつでも、hashを考えてください。ハッシュには、非常に優れた属性がいくつかあります。

  • そのキーは 1 つしか存在できません。すべての数値を、その数値をキーとするハッシュに格納したとします。キーのリストにはすべての番号が含まれており、重複はありません。
  • 高速キー検索: 数値をハッシュに格納し、再び数値でキーを設定したとします。前にその数字を見たことがありますか?そのキーが存在するかどうかを確認します。高速でシンプル。

ここで手短にやり直します。

#! /usr/bin/env perl
use strict;
use feature qw(say);
use warnings;
use autodie;

use warningsと同様にあることに注意してくださいuse strictuse strictエラーの約 90% を検出できる人に伝えます。まあ、use warningsエラーのさらに 9.99% をキャッチできます。警告は、未定義の変数を出力しようとした場合や、おそらく問題を引き起こす可能性のある不適切な構文に関するものです。

use feature qw(say);sayの代わりに使用できますprint。ではsay、NL が含まれているため、常に使用する必要はありません\n。あまり聞こえませんが、いいですね。use autodieファイルを開くことができない場合、プログラムを自動的に強制終了するなどのことを行います。これは、Perl をやや例外ベースの言語に変えます。このようにして、何かをテストするのを忘れた場合、プログラムが知らせてくれます。

use constant {
    FILE         => '/path/to/file',
    OUTPUT       => '/path/to/output/file',
};

定数は、定数が必要なときに使用する必要があるものです。

open my $numfile_fh, "<", FILE;  #No need for die
open my $output_fh, ">", OUTPUT;
my %number_hash;
while ( my $number = <$numfile_fh> ) {
    chomp $number;   #Always chomp after you read
    if ( not exists $number_hash{$number} ) {
        $number_hash{$number} = 1;
        say $output_fh "$number";
    }
}
close $numfile_fh;
close $output_fh;

私はあなたのファイルを一度に 1 つずつ読み込んでいますが、単純にファイルに書き込むのではなく、%number_hashその番号を既に認識しているかどうかを確認します。持っていない場合は、自分の中に保存して%number_hash印刷します。ロジックは次のように記述できます。

while ( my $number = <$numfile_fh> ) {
    chomp $number;   #Always chomp after you read
    next if exists $number_hash{$number};

    $number_hash{$number} = 1;
    say $output_fh "$number";
}

これがループ ロジックを記述するためのより良い方法であると言う人もいます。このスタイルでは、例外 (繰り返しである数字) を排除してから、デフォルトのケースを処理します (読み取った数字を出力してハッシュに保存します)。

これは実際にはリストの順序を変更していないことに注意してください。数値を読み込んで、それが重複していない限り、読み込んだのと同じ順序で出力します。数値を並べ替えて並べ替えたい場合は、次の 2 つのループを使用します。

while ( my $number = <$numfile_fh> ) {
    chomp $number;   #Always chomp after you read
     $number_hash{$number} = 1;
}

for my $number ( sort keys %number_hash ) {
    say $output_fh "$number";
}

数値が配列に含まれているかどうかをわざわざテストしないことに注意してください。とにかく、ハッシュは値ごとに1つのキーしか持てないため、その必要はありません。

于 2013-05-28T14:55:48.340 に答える