Perl:'半'无限循环?

时间:2012-07-21 22:04:23

标签: perl

我这里有一个正常工作的代码,它适用于8或10封电子邮件,但如果你只发了20封电子邮件,它就永远不会完成计算。也就是说,它不是一个无限循环,否则它永远不会计算任何东西。此外,如果您只使用10封电子邮件但要求它制作超过2个的列表,则会发生同样的事情。是的,正如所指出的那样,有一段时间(@address)和其中某处,推送到地址,这就是原因。我试图用另一个名称替换它所推送的那个数组,但是我得到了奇怪的错误,比如从列表中选择一封电子邮件,它会抱怨虽然有严格的引用,但我不能使用它...... 我理解100%的代码直到'map'行。在那之后,没那么多......

如果我们看一下这部分:

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

有人会说变量$ address必须被推送到@addresses,因为那是数据源(因此指出循环),但是......'移动'但是,抱歉,'移动'是一个哈希。你不能将变量推入哈希值,是吗?应该'移动'实际上是一个数组而不是哈希?这是我迷路的地方

我正在考虑这个问题,但是......这只是直觉,而不是真正的知识

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

2 个答案:

答案 0 :(得分:0)

我想我已经解决了这个问题,将“Konerak”的评论作为出发点。事实上,这个问题永远不会减少。因为我对参考数组知之甚少,所以我有点迷失,但不知何故,在阅读代码时,我试图找到预期行为的相似性。

因此我创建了另一个名为@reserva的数组,我写了这个:

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

而不是

 push @addresses, $address;

现在,无论我输入多少封电子邮件,我都会获得所需的大小。我尝试了1000并且在不到一秒钟内没有问题。

所以,这是完整的代码

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

答案 1 :(得分:0)

这是一些曲折的代码,难怪你在跟踪它时遇到了麻烦。我实际上并不确定代码的主体应该完成什么,但是你可以通过不使用while (@array)至少避免无限循环 - 而是使用foreach my $item (@array)而你将迭代它并且避免因修改循环内的数组而产生的奇怪行为。

chomp(@addresses);  # chomp called on an array chomps each element 
foreach my $address (@addresses) {
    # Do work here
}