【问题标题】:What is the proper syntax for storing an array into a Perl hash?将数组存储到 Perl 哈希中的正确语法是什么?
【发布时间】:2010-12-17 01:55:13
【问题描述】:

我正在创建一个这样的新对象:

TestObject->new(@array1, @array2)

我的new 方法如下所示:

sub new {
  my $class = shift;
  my $self = {};

  my $self->{Array1} = shift;
  my $self->{Array2} = shift;

  bless($self, $class);

  return $self;
}

作为访问数据的简单测试,我正在尝试这个,然后一旦我开始工作,我就可以构建更有意义的逻辑:

sub mymethod {
  my $self = shift;
  my $param = shift;

  my $array1Value = shift(my $self->{Array1});
  my $array2Value = shift(my $self->{Array2});

  print $array1Value." ".$array2Value;
}

但是当我打电话给mymethod 时,我得到了这个错误:

Type of arg 1 to shift must be array (not hash element) at Tests/MyObject.pm line 21, near "})"

建议?我读过this page on Perl data structures,但他们没有使用shift 方法的参数创建数组散列的示例。所以我的问题可能就在那里。

【问题讨论】:

  • 这到底是什么? shift(my $self->{Array1})

标签: perl arrays data-structures hash


【解决方案1】:

当您将数组作为参数传递时,它们会被展平。您可以传递对它们的引用。见perlsub

#!/usr/bin/env perl

package foo;

sub new {
    my $class = shift;
    my $self = {};

    $self->{Array1} = shift;
    $self->{Array2} = shift;

    bless($self, $class);

    return $self;
}

sub mymethod {
  my $self = shift;
  my $param = shift;

  my $array1Value = shift( @{$self->{Array1}} );
  my $array2Value = shift( @{$self->{Array2}} );

  print "$array1Value $array2Value\n";
}

package main;

my @a = ( 0, 1, 2);
my @b = ( 3, 4, 5);
my $o = new foo( \@a, \@b );;
$o->mymethod;

【讨论】:

【解决方案2】:

在这种情况下,您必须使用指向数组的指针,而不是数组:

  TestObject->new([@array1], [@array2])

后来

my $array1Value = shift(@{$self->{Array1}});

【讨论】:

  • new(\@array1, \@array2) 会更高效,因为 [@foo] 创建了一个新的匿名数组,然后(浅)将 @foo 的元素复制到其中,而 \@foo创建对现有数组的引用。另请注意,在 Perl 中,我们通常将 this 称为引用,而不是指针。 Perl 中没有类似 C 的指针。
  • 这正是因为我通常使用 [] 语法而不是 \@。该对象应该封装数据;它不能对其上下文之外的那些数组发生的任何事情负责。只有在我们必须处理大量数据并微调数据复制的极少数情况下才会提出效率问题 IMO
  • catwalk: 那么你可能想要一个深拷贝(例如 Storable::dclone); [@foo] 将复制 @foo 中的值,但如果值本身是引用,则新数组仍将连接到可从旧数组访问的值。
  • [替换以前的,完全错误的评论:] 实际上,封装问题应该归咎于被调用者。让调用者使用他想要的任何东西;如果您想对参数的更改保持隔离,请在被调用者中制作副本。
  • 你们刚刚提出了一个非常常见的测试用例:将一些数据传递给一个方法,然后在调用者中更改该数据;对象的数据版本是否也会改变?令人惊讶的是,这一点被忽视的频率如此之高!
【解决方案3】:

您正在移动一个数组引用而不是一个实际的数组。

你可能正在寻找的语法是:

my $array1Value = shift @{ $self->{Array1} };
my $array2Value = shift @{ $self->{Array2} };

注意如何使用@ 取消引用数组。

【讨论】:

  • 还要注意这将修改原始数组,而不是它的副本。
  • 我想这就是他想要的,因为他使用shift 而不是下标,但这仍然值得一提。 +1
【解决方案4】:

您需要取消对数组 ref 的引用:

@{$self->{Array2}}

顺便说一句,如果您使用的是 OO,我强烈建议您查看 Moose。它会让你的生活更轻松!

【讨论】:

  • 我认为您也需要首先引用它,对吧?喜欢->new(\@array1, \@array2)
  • 那行得通。当我尝试这样做时,我只是尝试了@$self->{Array2},忘记了 $self->{Array2} 周围的 { 和 }。
  • 这个答案完全忽略了将真实数组传递给函数的问题,这意味着代码可以编译但会DTWT。
猜你喜欢
  • 2012-03-18
  • 2013-04-25
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
相关资源
最近更新 更多