1

私はここに機能するコードを持っています、それは8または10の電子メールでうまく機能します、しかしあなたがちょうど20の電子メールを置くならば、それは計算を決して終わらせません。つまり、それ以外の場合は何も計算されないため、無限ループではありません。また、10通のメールだけを使用して2つ以上のリストを作成するように依頼した場合も、同じことが起こります。はい、指摘されているように、while(@address)があり、そのどこかにアドレスへのプッシュがあります。それが理由です。別の名前でプッシュされた配列を置き換えようとしましたが、リストから1つのメールを選択するなどの奇妙なエラーが発生し、厳密な参照がオンになっていると、それを使用できないと文句を言います... 100%理解しています'map'行までのコード。その後、それほど多くはありません...

この部分を見ると:

push @addresses, $address;
    $moved{$address}++;
#     say "pushing $address to moved"; # debug

変数$addressは、@ addressesではなく、データのソースであるため(したがって、ループが指摘されているように)プッシュする必要がありますが、..'moved'にプッシュする必要がありますが、申し訳ありませんが、'moved'はハッシュ。変数をハッシュにプッシュすることはできませんね。次に、「移動」は実際にはハッシュではなく配列である必要がありますか?これは私が迷子になるところです

代わりにこれについて考えていましたが...それは単なる直感であり、実際の知識ではありません

push @{ $moved[$i] }, $address
4

2 に答える 2

0

「コネラック」からの発言を出発点として、解決したと思います。確かに、問題は決して減少しないリストでした。私は参照配列に精通していないので、ちょっと迷いましたが、どういうわけかコードを読んで、予想される動作の類似性を見つけようとしました。

したがって、@ reservedaという別の配列を作成し、次のように記述しました。

push @ {$reserva [$i]}, $address 

それ以外の

 push @addresses, $address;

これで、入力する電子メールの数に関係なく、必要なサイズのリストが表示されます。1000で試してみましたが、1秒足らずで問題ありませんでした。

だから、ここに完全なコードがあります

use strict;
use warnings;
use feature 'say';
use Data::Dumper;

my $only_index = 3; # Read from command line with $ARGV[0] or use Getopt::Long

my %blacklist = (       # Each key in this hash represents one index/day
  '2' => [ 'a', 'b' ],  # and has an arrayref of domains that have replied on
  '3' => [ 'c' ],       # that day. We look at all keys smaller than the current
);                      # index in each iteration and ignore all these domains 

my @domains; # holds the domains we have already seen for each list
my @lists = ([]); # Holds all the lists
my %moved; # the addresses we moved to the back
my $i = 0;
my @addresses = <DATA>;

while (@addresses) {
  my $address = shift @addresses;
  chomp $address;
  $address =~ m/@([a-zA-Z0-9\-.]*)\b/;
  my $domain = $1;

  # If the domain has answered, do not do it again 
  next if 
    grep { /$domain/ } 
    map { exists $blacklist{$_} ? @{ $blacklist{$_} } : () }  (0..$i);
  $i++ if (@{ $lists[$i] } == 2 
           || (exists $moved{$address} && @addresses < 1));
  if (exists $domains[$i]->{$domain}) {
    push @addresses, $address;
    $moved{$address}++;
#     say "pushing $address to moved"; # debug
  } else {
    $domains[$i]->{$domain}++;
    # send the email
#     say "added $address to $i";      # debug
    push @{ $lists[$i] }, $address;
  }
}
# print Dumper \@lists;           # Show all lists
print Dumper $lists[$only_index]; # Only show the selected list
1;


__DATA__
1@a
2@a
3@a
1@b
2@b
1@c
2@c
3@c
1@d
2@d
3@d
4@d
1@e
1@f
1@g
1@h
4@a
5@a
4@c
于 2012-07-22T08:50:28.013 に答える
0

それはいくつかのねじれたコードです、それをフォローするのに問題があるのも不思議ではありません。コードの本体が何を達成するのかは実際にはわかりませんが、使用しないことで少なくとも無限ループを回避できますwhile (@array)-foreach my $item (@array)代わりに使用すると、それを繰り返して、変更から生じる奇妙な動作を回避できますループ内の配列。

chomp(@addresses);  # chomp called on an array chomps each element 
foreach my $address (@addresses) {
    # Do work here
}
于 2012-07-23T15:24:51.073 に答える