加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – List :: MoreUtils mesh或’zip’功能

发布时间:2020-12-15 21:33:29 所属栏目:大数据 来源:网络整理
导读:所以这个问题纯粹是为了学习和好奇,但任何人都可以解释下面的功能如何工作? sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) { my $max = -1; $max $#$_ ( $max = $#$_ ) foreach @_; map { my $ix = $_; map $_-[$ix],@_;
所以这个问题纯粹是为了学习和好奇,但任何人都可以解释下面的功能如何工作?
sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) {
    my $max = -1;
    $max < $#$_ && ( $max = $#$_ ) foreach @_;
    map {
        my $ix = $_;
        map $_->[$ix],@_;
    } 0 .. $max;
}

来自List::MoreUtils模块.我在我的一个应用程序中使用它,我碰巧看到源代码,这让我觉得我根本不知道perl!任何人都可以解释这个疯狂吗? :) 谢谢!

解决方法

我不会覆盖原型部分(暴徒说他会的).

这是一个更可读的版本 – 理想情况下,它应该是自明的

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,... 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,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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读