Perl:方法和返回的数组

时间:2013-08-14 09:02:15

标签: arrays perl

我做了几个方法。计算质心,根据质心平移矩阵。计算质量中心工作正常。 x,y,z值很好。但是,我在translateMatrixOperation子方法中传递和返回数组时遇到了麻烦。实际上,translateMatrixOperation返回(\ @translatematrix),我无法访问另一个调用子方法的方法中的元素。这有什么问题?

my @ref = calculateCenterMass(@matrix);
my $x = $ref[0];
my $y = $ref[1];
my $z = $ref[2];
print "Center of Mass for Matrix Above\n";
printf("X:%.3f,Y:%.3f,Z:%.3f\n\n",$x,$y,$z);
my @tempMatrix = translateMatrixOperation($x,$y,$z,\@matrix);
-----------------------------------------
sub translateMatrixOperation
{
  my ($x, $y, $z, $translatematrix) = @_;
  my $arrsize = @$translatematrix;
  for(my $i = 0; $i < $arrsize; $i++)
  {
    for(my $j = 0; $j < $arrsize; $j++)
    {
        if ($j == 0)
        {
            $translatematrix->[$i][$j] -= $x;
        }
        elsif ($j == 1)
        {
           $translatematrix->[$i][$j] -= $y;
        }
        elsif ($j == 2)
        {
            $translatematrix->[$i][$j] -= $z;
        }
     }
  }

 return (\@translatematrix);

}

2 个答案:

答案 0 :(得分:5)

子例程返回对数组的引用。您将结果存储在数组@tempMatrix中。因此,整个矩阵存储在$tempMatrix[0]

这可能不是你想要的。如果子例程返回引用,请使用标量变量来保留它,或者在将结果赋给数组之前取消引用它:

my $array_ref = translateMatrixOperation($x,$y,$z,\@matrix);
my @array     = @{ translateMatrixOperation($x,$y,$z,\@matrix) };

后一种选择速度较慢且占用内存较多,因为必须复制该数组。

答案 1 :(得分:0)

返回数组引用而不仅仅是返回数组的选择通常可以归结为大小。

如果要传输小数组,我只需用:

编写
return @translatematrix;

如果要传输大型数组(大到足以影响性能),那么我可能会考虑返回一个引用。

我不确定你应该将它们称为矩阵,因为它们似乎是cartesian coordinates的数组。这会更容易思考。


无论如何,您的代码非常冗长,而且很可能是错误的。

  • 当它不需要时,它使用C样式进行循环。

    foreach循环通常更快,并且它们更清楚地表明它们正在循环。

  • 它循环遍历内部数组,即使你几乎总是会改变3个值。

  • 你的内部for循环使用外部数组的长度,而不是内部数组。

    如果外环少于3个元素,则会出现问题 这也意味着当你的外部数组很大时,你的代码会花费大量的时间做任何事情。

    这也是使用foreach循环的另一个原因,你无法将测试部分弄错。

  • 您可以修改原始数组的元素。

  • 您将返回对您在子例程中实际未使用的数组的引用。

    我只能假设您的代码中没有use strict;use warnings;,或者您已在代码中的其他位置声明了@translatematrix

这是一个仍然修改原始数组的版本。 (也许这就是你真正想要的)

use strict;
use warnings;
my @matrix = ...;

# no need for a temporary variable
my ($x,$y,$z) = calculateCenterMass(@matrix);

print "Center of Mass for Matrix Above\n";
printf( "X:%.3f,Y:%.3f,Z:%.3f\n\n", $x, $y, $z );

# it returns a reference, not an array.
my $tempMatrix = translateMatrixOperation( $x, $y, $z, \@matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, $translate_matrix) = @_;

  for my $xyz ( @$translate_matrix ){
    $xyz->[0] -= $x;
    $xyz->[1] -= $y;
    $xyz->[2] -= $z;
  }

  return @$translate_matrix if wantarray;
  return $translate_matrix;
}

这是一个创建新数组的版本。

my $tempMatrix = translateMatrixOperation( $x, $y, $z, @matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, @coord) = @_;

  # This is here in case you give it an array reference like you did before.
  # It is quite fragile, you should remove it if you don't need it.
  if( 1
    and @coord == 1
    and ref( my $aref = $coord[0] ) eq 'ARRAY'
    and ref($aref->[0]) eq 'ARRAY'
  ){
    @coord = @$aref;
  }


  # create a new list
  my @return = map{
    # of a new array refs based on the old ones
    [ $_->[0] - $x, $_->[1] - $y, $_->[2] - $z, @$_[3..$#$_] ]
    # the @$_[3..$#$_] part may be unnecessary
    # it should be removed if that is the case
  } @coord;

  return @return if wantarray;
  return \@return;
}

如果您删除我认为不需要的部件,则会很短暂

my $tempMatrix = translateMatrixOperation( $x, $y, $z, @matrix );

sub translateMatrixOperation {
  my ($x, $y, $z, @coords) = @_;

  my @return = map{
    [ $_->[0] - $x, $_->[1] - $y, $_->[2] - $z ]
  } @coords;

  return @return if wantarray;
  return \@return;
}

您还应该找出一个更好的名称,translateMatrixOperation不是很具描述性。