Perl:“半”无限循环?

Posted

技术标签:

【中文标题】Perl:“半”无限循环?【英文标题】:Perl: the 'semi' infinite loop? 【发布时间】:2012-07-21 22:04:22 【问题描述】:

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

如果我们看这部分:

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

有人会说必须将变量 $address 推入,而不是推入@addresses,因为那是数据的来源(因此指出了循环),而是推到 ..'moved' 但是,对不起,'移动'是一个哈希。您不能将变量推送到哈希中,可以吗?那么“移动”实际上应该是一个数组而不是一个散列吗?这是我迷路的地方

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

push @ $moved[$i] , $address

【问题讨论】:

在调试器中运行它,并监视@addresses。因为你在做一个while @addresses,然后你又做了一个push @adresses,我的小指告诉我要注意一个永远不会减少的列表...... 【参考方案1】:

我想我已经解决了,以“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

【讨论】:

【参考方案2】:

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

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

【讨论】:

以上是关于Perl:“半”无限循环?的主要内容,如果未能解决你的问题,请参考以下文章

如何可视化vue无限更新循环的无限循环

无限循环与嵌套循环

检查空无限循环中的选项与做一些无限循环

C++入门基础知识[3]——循环嵌套循环无限循环

Python无限循环

00014_无限循环