说我在Perl中有类似以下的数组:
@names = ("one", "two", "three", "four", "five", "six");
我想在预定义大小的子数组(“chunks”)中循环遍历此数组。更具体地说,我想要一个变量,例如我的循环中的@chunk
在每次迭代中保存相应的子数组:
for ? {
say @chunk;
}
例如,如果我使用2
作为我的子数组/块大小,我们将迭代 3 次,@chunk
将在以下值中保持以下值:
("one", "two")
("three", "four")
("five", "six")
如果我使用4
作为我的块大小,它将只迭代两次,而@chunk
将保持:
("one", "two", "three", "four")
("five", "six") # Only two items left, so the last chunk is of size 2
在Perl中是否有任何内置插件/库可以轻松完成此操作?
答案 0 :(得分:5)
您可以使用natatime
my @names = qw(one two three four five six);
# Chunks of 3
my $it = natatime 3, @names;
while (my @vals = $it->())
{
print "@vals\n";
}
(一次读取 N )从List::MoreUtils执行此操作:
natatime
要更改“块”大小,只需将第一个参数更改为# Chunks of 4
my $it = natatime 4, @names;
:
{{1}}
答案 1 :(得分:4)
一种方法是使用内置的splice
函数:
my @names = qw(one two three four five six);
while (@names) {
my @chunk = splice @names, 0, 2;
say "@chunk";
}
请注意,这会破坏@names
数组;如果这是一个问题,请先复制一份。
如果您愿意,您甚至可以将其封装在一个函数中,如下所示:
sub chunk_map (&$@) {
my $code = shift;
my $n = shift;
my @out;
while (@_) {
push @out, $code->(splice @_, 0, $n);
}
return @out;
}
由于prototype,你可以像内置函数map
一样使用它,除了它需要一个额外的第二个参数给出块大小,并将块传递给回调功能在@_
而非$_
。你可以使用它,例如像这样:
chunk_map { say "@_" } 2, @names;
甚至:
say "@$_" for chunk_map { [@_] } 2, @names;
编辑:要预先告知将有多少块,您可以简单地将数组的长度除以块大小并将其四舍五入。要知道到目前为止你处理了多少块,最简单的方法可能就是维持一个计数器:
my @names = qw(one two three four five six);
my $n = 4;
my $chunks = int((@names + $n - 1) / $n); # round @names / $n up
my $i = 0;
while (@names) {
$i++;
my @chunk = splice @names, 0, $n;
say "chunk $i / $chunks: @chunk";
}
或者,使用上面给出的chunk_map
函数:
my @names = qw(one two three four five six);
my $chunks = my @chunks = chunk_map { [@_] } 4, @names;
foreach my $i (1 .. @chunks) {
my @chunk = @{ $chunks[$i-1] };
say "chunk $i / $chunks: @chunk";
}