2016-07-29 145 views
2

我在网上看,每个人似乎都说他们互换使用。但是,当我遍历数组时,它给了我不同的结果。我有一个约数组的数组。 60个字符串元素,并过滤掉在另一个数组中匹配的内容。但是,当我使用foreach,只看到了45个元素的数组,所以当我打印的最终结果,它没有过滤所有的东西。Perl:为什么for和foreach会给我不同的结果?

只有当我用for它的工作,因为我想要的。这背后的原因是什么?

我设法解决这个问题,现在我只是想了解这种工作方式。谢谢!

编辑:所以我没有提供任何例子所以这里就是我所做的:

my $i = 0; 
foreach my $item (@array){ 
    print "\n$i : $item"; 
    foreach my $exclude_item (@exclude){ 
     chomp $exclude_item; 
     if ($exclude_item eq $item){ 
      print "\nDEBUG: Removing $item"; 
      splice @array, $i, 1; 
     } 
    } 
    $i++; 
} 

上面没有给我的@array的完整列表,所以当我打印的最终结果,有元素里面应该已经过滤了。

所以,我想这不是(这工作,因为我想):

for (my $i=0; $i < scalar @array; $i++){ 
    print "\n$i : $array[$i]"; 
    foreach my $exclude_item (@exclude){ 
     chomp $exclude_item; 
     if ($exclude_item eq $array[$i]){ 
      print "\nDEBUG: Removing $array[$i]"; 
      splice @array, $i, 1; 
     } 
    } 
} 

只是额外的信息,该@array是通过搜索多个文件夹中的子目录的列表中创建。可能@array包含重复项。

+9

其他的不同。 “for”和“foreach”与词法分析器完全没有区别。他们是两个完全相同的名字。 – hobbs

回答

14
# Foreach loop        \   
foreach my $item (@array)      > same  \ 
for my $item (@array)      /   \ 
                  > different 
# Augmented while loop      \   /
for (my $i=0; $i < scalar @array; $i++)  > same /
foreach (my $i=0; $i < scalar @array; $i++)/

不得修改数组在你迭代。从perlsyn,

如果LIST的任何部分是一个数组,如果你splice循环体中添加或删除元素,例如foreach会得到非常困惑。所以不要这样做。

因此,

foreach (@array){ 
    ... 
    splice @array, $i, 1; # XXX Error 
    ... 
} 

注意,可以安全地修改的阵列在其上是你迭代的元素。

foreach (@array){ 
    $_ = uc($_); # ok 
} 

最后,一个更好的解决方案:

chomp(@exclude); 

my %exclude = map { $_ => 1 } @exclude; 

@array = grep { !$exclude{$_} } @array; 
被简单得多

除此之外,它扩展非常非常好[1]


  1. 它为O执行(E + A)时,而OP的为O执行(E * A )时间。
+1

我真的很讨厌/爱你们让我感到多么愚蠢..说这个,谢谢澄清!我不明白你的解决方案,所以我将不得不在我周五晚上花这个。 –

+0

'my%exclude = map {$ _ => 1} @exclude;'创建一个查找表,因此如果应该排除字符串,可以高效地查找。 '@array = grep {!$ exclude {$ _}} @array;'保留'@ array'的所有元素,除了查找表中的元素外。 – ikegami

+0

只是为了完整性,散列切片方法'my%exclude; @exclude {@exclude} =(1)x @ exclude'再次快两倍。如果你只做了一次,它可能不值得两条线。 – mbethke

6

当人们说他们互换使用时,他们的意思是foreach关键字只是for关键字的同义词。这意味着下面的两行表示完全一样的东西:

foreach my $item (@array) {...} 
for my $item (@array) {...} 

为免生疑问,我会忽略foreach关键字,并使用下面只for

下面两行,正如你所看到的,不表现相同:

for my $item (@array) {...} 
for (my $i = 0; $i < scalar @array; $i++) {...} 

manual建议不要在第一行的循环体添加或删除在@array元素,不说结果会是什么。

如果第二行的循环体在$i处或之前删除@array中的元素,结果将是跳过新位置$i处的元素。如果在$i或之前添加元素,结果将是旧位置$i处的元素将被循环再次看到。

相关问题