gpt4 book ai didi

perl - List::MoreUtils 网格或 'zip' 函数

转载 作者:行者123 更新时间:2023-12-04 00:58:54 25 4
gpt4 key购买 nike

所以这个问题纯粹是出于学习目的和好奇心,但是任何人都可以解释下面的函数是如何工作的吗?

sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {
my $max = -1;
$max < $#$_ && ( $max = $#$_ ) foreach @_;
map {
my $ix = $_;
map $_->[$ix], @_;
} 0 .. $max;
}

来自 List::MoreUtils模块。我在我的一个应用程序中使用它,我碰巧看到了源代码,这让我觉得我根本不知道 perl!谁能解释这种疯狂? :) 谢谢!

最佳答案

我不会涵盖原型(prototype)部分(暴民说他会)。

这是一个更易读的版本 - 理想情况下,它应该是不言自明的

sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {

# Calculate the maximum number of elements in each of the array refs
# we were passed:

my $maxLength = 0;
foreach my $array_ref (@_) { # @_ is all arrey refs passed in
if ($maxLength < @$array_ref) {
# we found an array longer than all previous ones
$maxLength = @$array_ref;
}
}

    # If you represent the arrays as a matrix:
# ARR1 = [ a1e1, a1e2, .... a1eN],
# ARR2 = [ a2e1, a2e2, .... a2eN],
# ...
# ARR2 = [ aMe1, aMe2, .... aMeN];
# Then, we are simply walking through the matrix;
# each column top to bottom then move on to next column left to right
# (a1e1, a2e1, ... aMe1, a1e2, a2e2, ... aMeN)

my @results;
for (my $index = 0; $index < $maxLength; $index++) { # Iterate over columns
foreach my $array_ref (@_) { # Iterate over per-row cells in each column
push @results, $array_ref->[$index];
}
} ;
}

这是一个评论的原始版本
sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {

# Calculate the largest index in each of the array refs
# @_ is an array of all the input arrayrefs
# $_ will be one of the array refs in a foreach loop
# $#{$X} is the largest index in arrayref X; thus
# $#$_ is the largest index in arrayref $_
my $max = -1;
$max < $#$_ && ( $max = $#$_ ) foreach @_;

# Return a list, obtained by looping
# over every index from 0 to the maximal index of any of the arrays
# Then, for each value of the index ($ix), push into the resulting list
# an element with that index from each of the arrays.
map {
my $ix = $_;
map $_->[$ix], @_;
} 0 .. $max;
}



此方法中不寻常的事情之一是 function signature (prototype) .
sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {

正如@mob 和@ikegami 在评论中明智地指出的那样,

... It instructs Perl to expect between 2 and 32 named arrays, and to pass them to the function (in @_) as array references. So if you call mesh @a,@b,@c, then @_ in mesh is set to (\@a,\@b,\@c) rather than one "flat" list with all the individual elements of @a, @b, and @c (mob)
... They technically don't need to be named, just dereferenced. e.g. @$ref and @{[qw( foo bar )]} work just as well as @a. In other words, it has to start with @ (and not be a slice). (ikegami)



换句话说,以下 2 个调用的行为相同
my @a1 = (1);
my @a2 = (2);
sub mesh_prototype(\@\@) { print "$_->[0]\n" }
sub mesh_pass_arrayref() { print "$_->[0]\n" }
mesh_prototype(@a1, @a2);
mesh_pass_arrayref(\@a1, \@a2);

这样做是为了您可以将单个数组(而不是 arrayrefs)作为参数传递给行为类似于内置函数的函数(例如 map/ sort )

回答 Zaid 关于如果将 1 或 33 个数组作为参数列出来调用 mesh() 会发生什么的问题。 ,它会产生一个编译时错误:
Not enough arguments for main::mesh at mesh.pl line 16, near "@a1)"
Execution of mesh.pl aborted due to compilation errors.

Too many arguments for main::mesh at mesh.pl line 16, near "@a2)"
Execution of mesh.pl aborted due to compilation errors.

关于perl - List::MoreUtils 网格或 'zip' 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11474697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com