1

2つのハッシュ-> %a%b。ハッシュ%atemp.txt

my %a = map{
  my $short = substr($_,12);
  $count++ => {$short => $_};
  } @a;

my %b = map {
   $_ => $_;
  } @b;

%a = (
    '1' =>  {'We go lunch' => 'We go lunch 9 pm'},
    '2' =>  {'We go break' => 'We go break 8 pm'},
    '3' =>  {'We go lunchy' => 'We go lunchy 8 pm'}
);

%b = (
    'We go lunch' => 'We go lunch',
    'We go break' => 'We go break',
    'We go lunchy' => 'We go lunchy'
);

foreach my $key (keys %a){
  foreach my $key2 (keys %{$a{$key}}){
      if(exists $b{$key2}){
      delete $a{$key}{$key2};
      delete $a{$key};
  }
  }
}

my @another;
foreach my $key ( sort {$a<=>$b} keys %a) {
   foreach my $key2 (keys %{$a{$key}}){
      $another[$count] = $a{$key}{$key2};
      $count++;
   }
}

どうすればこれをスピードアップできますか?私のハッシュは変ですか?@anotherの25144行の単語を出力するのに30秒かかりましたtemp.txt

のハッシュのハッシュを作成する必要があり%aますか?%b{$key}その理由は、の値を%a削除したいからです。おそらくmapとgrepを使用して、これを行うためのより良い方法があれば、私はまだPerlを学んでいます。そしてより良いアルゴリズム?

以前の回避策

すべての@bがすべての@aよりも短い文字列であるが、それでも@a内にある場合。使ってみた

foreach (@b) { 
my $source = $_; 
@another = grep !(/$source/i), @a;}

しかし、それでも機能しません。私は混乱していたので、このハッシュのハッシュを%aに入れ、@ bからハッシュ%bを作成して、@aの@bのすべてのインスタンス値を削除しました。これは奇妙なハッシュとして出てきます。笑

4

2 に答える 2

2

ここには不明な点がいくつかあります%b。たとえば、どのように構築されているかなどです。そうでなければ、いくつかの観察:

の代わりに別の配列を使用する必要があります%a

  my @c = map{
    { "".substr($_,12) => $_}
   } @a;

すでに%b定義している場合は、次の方法でさらに最適化できます。

my @another = grep !exists $b{ substr($_,12) }, @a;

お役に立てれば

また、常に use strict;use warnings;プログラムの最初に忘れないでください。

説明:

あなたのコードはすべてを に入れ%a、それをトラバースし、そこにあるべきではないものを排除します。grep必要な結果だけを簡単に配列に保持できると思います。

最適化されたコードは次のようになります。

use strict;
use warning;

my %b = (
    'We go lunch' => 'We go lunch',
    'We go break' => 'We go break',
    'We go lunch' => 'We go lunch'
);

#add code that initially fills @a

my @another = grep { !exists $b{ substr($_,12) } } @a;
于 2012-11-27T07:52:46.977 に答える
1

あなたはとても混乱しているようです。まず第一に、文字列の 12 番目以降substr $_, 12のすべての文字を返すため、あなたが言うデータ構造を作成しません。次に、ハッシュのハッシュを配列の配列として使用しています。これは、キーがシーケンスにギャップのない整数であり、保存している値が単純な文字列のペアであるためです。%a

私たちにとって最大の問題は、あなたがこのすべてにおいてあなたの目標を説明していないことです.

のどの文字列でも始まらない@anotherからのすべての行を含む配列で終了したいということです。それは正しいですか?temp.txt@b

array から正規表現を作成@bし、ファイルを読みながら各行をチェックすることでそれを行います。

このプログラムはデモンストレーションします。前者は変数のひどい@b名前であるため、配列の名前を変更しました。正規表現は、配列の各要素の前に を付けて正規表現を文字列の先頭に固定し、追加して単語の境界を強制する (たとえば、が一致しないようにする) ことによって構築されます。次に、代替演算子を使用してすべての要素を結合し、 のいずれかの行で始まる文字列に一致する正規表現を生成します。@exclude^\blunchlunchy|@exclude

その後、ファイルを読み、正規表現に対して各行をチェックし、@another一致しない行にプッシュするのは簡単なことです。

現状では、プログラムはDATAファイル ハンドルから読み取り、ソースにテスト データを含めることができることに注意してください。open行のコメントを解除し、行を削除して変更する必要がありmy $fh = *DATAます。

use strict;
use warnings;

#open my $fh, '<', 'temp.txt' or die $!;
my $fh = *DATA;

my @exclude = (
  'We go lunch',
  'We go lunchy',
  'We go break',
);

my $exclude_re = join '|', map "^$_\\b", @exclude;

my @another;
while (my $line = <$fh>) {
  chomp $line;
  push @another, $line unless $line =~ $exclude_re;
}

print "$_\n" for @another;

__DATA__
We go breakfast 6 am
We go lunch 9 pm
We go break 8 pm
We go lunchy 8 pm
We go supper 7 pm

出力

We go breakfast 6 am
We go supper 7 pm
于 2012-11-27T13:09:07.987 に答える