【问题标题】:splice doesnt work well in loop in perlsplice 在 perl 的循环中不能很好地工作
【发布时间】:2014-07-16 14:22:29
【问题描述】:

我试图理解拼接。 我想使用拼接一个一个地删除数组中的所有元素。但我得到的输出仍然很奇怪。我无法理解。谁能解释一下:

代码

my @arr1=(1,2,3,4,5,6,7,8,9,10);

foreach my $num(@arr1)
{
    print $_ foreach (@arr1);
    print "\n Popping $num\n";
    print "[0] is $arr1[0] and current element is $num \n";
    splice @arr1,0,1;
    print "\n";
}

输出:

 12345678910
 Popping 1
[0] is 1 and current element is 1

2345678910
 Popping 3
[0] is 2 and current element is 3

345678910
 Popping 5
[0] is 3 and current element is 5

45678910
 Popping 7
[0] is 4 and current element is 7

5678910
 Popping 9
[0] is 5 and current element is 9

【问题讨论】:

  • 为什么不使用popshift
  • 您正在执行的操作在 Perl 中称为shiftpop 将是 splice(@arr1, -1)。另外,print 是一个列表运算符,所以print $_ foreach (@arr1) 可以更简单地写成print @arr1
  • 您可以使用while ($_ = shift @array){print $_} 将数组的元素一个一个地删除。
  • @slade:这个问题被简化为指出我在原始问题中面临的问题。在我最初的问题中,我根据一些逻辑决定是否删除该元素。所以它并不总是我想要删除的 [0]。并且 imo shift 总是只删除第 0 个元素,对吗?

标签: perl


【解决方案1】:

foreach 创建一个包含原始 10 个数组元素的列表。您应该使用while 来修改数组。

use warnings;
use strict;

my @arr1=(1,2,3,4,5,6,7,8,9,10);

while (@arr1)
{
    my $num = $arr1[0];
    print $_ foreach (@arr1);
    print "\n Popping $num\n";
    print "[0] is $arr1[0] and current element is $num \n";
    splice @arr1,0,1;
    print "\n";
}

【讨论】:

  • while 只是测试数组以查看它是否为空。 splice 是消耗元素的对象。
【解决方案2】:

您在循环遍历数组时正在更改数组。 foreach 从 [0] 到 [1] 到 [2]。当您拼接 [0] 时,它会转到原始 [2] 的 [1]。当你拼接后,它会转到 [2],现在是原来的 [4],因为你已经拿走了第一个。

希望能稍微澄清一下。

你可以避免使用@arr1 作为循环控制器:

my @arr1=(1,2,3,4,5,6,7,8,9,10);

my $max = @arr1;
for (my $i=0; $i<$max; $i++) {
    print $_ foreach (@arr1);
    my $num = splice @arr1,0,1;
    print "\n Popping $num\n";
    print "[0] is $arr1[0] and current element is $num \n";
    print "\n";
}

【讨论】:

  • 顺便说一句,如果我在 foreach 在上下文中获取新元素之前进行更改,是否应该更新数组然后考虑它?
  • 我不确定你的意思。
【解决方案3】:

不要使用 foreach 修改要迭代的数组。

通常,解决方案通常是grep。例如下面处理@todo中的元素,将处理不成功的留在数组中。

sub process {
   ...
   return 0 if error;
   ...
   return 1;
}

@todo = grep { !process($_) } @todo;

在这种情况下,将foreach 替换为while

my @queue = 1..10;

while (@queue) {
   my $num = shift(@queue);
   print "Current element is $num\n";
}

【讨论】:

  • +1 表示 grep,cmets 建议这是 op 需要的
  • @RobEarl,添加了一个示例
猜你喜欢
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多