Perl - 拆分数组,并循环遍历其子数组

时间:2013-12-02 21:44:54

标签: arrays perl

说我在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中是否有任何内置插件/库可以轻松完成此操作?

2 个答案:

答案 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";
}