【问题标题】:Perl: difficulty understanding how to access list of list passed by reference?Perl:难以理解如何访问通过引用传递的列表列表?
【发布时间】:2014-06-29 02:35:24
【问题描述】:

这是我为遗传/进化算法编写的一个 perl 函数,用于比较来自各种文本文档的数据。我正在尝试降低复制部分:

我的函数调用get_2d_agree_groups,它通过引用返回一个“列表列表”,然后我需要根据需要进一步访问、修改、删除或添加到内部列表。 combine_arrayssplit_array 获取一维列表并对它们进行操作。我不知道如何正确访问这些内部列表以传递给函数。特别是当我尝试使用combine_arrays 附加到内部列表时,它会根据需要添加对列表的引用,而不是单个元素。

sub assemble_groups { #(parent1, parent2, new group size)
    my $holder = 0;
    my $parent1 = shift;
    my $parent2 = shift;
    my $num_groups = shift;
    my $blocks = get_2d_agree_groups(\@{${$parent1}{'groups'}},\@{${$parent2}{'groups'}});
    my @disagree_block = pop @{$blocks}; 
    my $agree_size = @{$blocks};
    while($agree_size < $num_groups)
    {
        my $index = getrand(0,($agree_size-1));
        my $size = @{${$blocks}[$index]};
        my $split_index = getrand(0,($size-1));
        my $new_array = split_array(\@{${$blocks}[$index]},$split_index);
        push @{$blocks}, $new_array;
        $agree_size++;
    }
    while($agree_size > $num_groups)
    {
        my $join1 = getrand(0,($agree_size-1));
        my $join2 = getrand(0,($agree_size-1));
        while($join1==$join2)
        {
            $join2 = getrand(0,($agree_size-1));
        }
        my @hold = ${$blocks}[$join2];
        my $test = join('',@hold);
        splice @{$blocks}, $join2, 1;
        combine_arrays(\@{${$blocks}[$join1]},\@hold); #right here
        $agree_size--;
    }
    my $i=0;
    my $disagree_size = @disagree_block;
    while (($i<$agree_size) && $disagree_size)
    {
        getnewgroup(\@{${$blocks}[$i]},\@disagree_block);
        $disagree_size = @disagree_block;
        $i++;
    }
    if($disagree_size)
    {
        combine_arrays(\@{${$blocks}[$i-1]},\@disagree_block); #right here
    }
    return $blocks;
}

相关功能:

sub combine_arrays { #(1d array 1, 1d array)
        my $group1 = shift;
        my $group2 = shift;
        my $group2_size = @{$group2};
        my $next = 0;
        for(my $i=0;$i<$group2_size;$i++)
        {
             $next = @{$group2}[$i];
             push @{$group1}, $next;
        }
}
sub split_array { #(array, index)
      my $old_array = shift;
      my $at = shift;
      my @new_array;
      my $old_size = @{$old_array};
      for(my $i=$at;$i<$old_size;$i++)
      {
           push @new_array, ${$old_array}[$at];
           splice @{$old_array}, $at, 1;
      }
      return \@new_array;
 }

【问题讨论】:

  • 什么是“列表列表”?你的意思是数组数组吗?

标签: perl reference pass-by-reference


【解决方案1】:
my @hold = ${$blocks}[$join2];

是不可读的版本

my @hold = $blocks->[$join2];

所以你可能想取消对数组的引用,

my @hold = @{ $blocks->[$join2] };

旁注

  • 如果您尚未启用 strictwarnings,请启用。
  • \@{${$blocks}[$join1]} 正在引用取消引用的数组,该数组等于 ${$blocks}[$join1](或 $blocks-&gt;[$join1]

【讨论】:

    【解决方案2】:

    您不需要 combine_array 函数。这就是push 的用途。

    对该函数的两次调用可以更改为

    combine_arrays(\@{${$blocks}[$join1]},\@hold); #right here
    ...
    combine_arrays(\@{${$blocks}[$i-1]},\@disagree_block); #right here
    

    只需致电push

    push @{$blocks->[$join1]}, @hold;
    ...    
    push @{$blocks->[$i-1]}, @disagree_block;
    

    【讨论】:

      猜你喜欢
      • 2018-06-29
      • 2014-12-18
      • 1970-01-01
      • 2011-06-05
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多