使用单个哈希的副本填充perl哈希数组

时间:2012-08-02 10:55:47

标签: perl reference copy perl-data-structures

我搜索过并搜索过,但我找不到任何我发现的代码。我很抱歉,如果这是重复旧的,但我现在花了2天试图让这10条线路正常工作,我在我的智慧结束时没有留下头发: - (

我正在运行Perl 5.8.8。

我想在Perl中填充哈希数组,使其包含我正在更新的单个哈希变量的多个副本。我的代码在这里:

use strict;
use warnings;

my @array;

my %tempHash = (state => "apple", symbol => "54", memberId => "12345");
push(@array, \%tempHash);

%tempHash = (state => "tiger", symbol => "22", memberId => "12345");
push(@array, \%tempHash);

%tempHash = (state => "table", symbol => "37", memberId => "12345");
push(@array, \%tempHash);

printf("%p %p %p\n", $array[0], $array[1], $array[2]);

foreach my $entry (@array){
    printf("state: %s\n", $entry->{state});
    printf("memberId: %s\n", $entry->{memberId});
    printf("symbol: %s\n\n", $entry->{symbol});
}

这会产生以下输出:

1868954 18688d0 18688c4
state: table
memberId: 12345
symbol: 37

state: table
memberId: 12345
symbol: 37

state: table
memberId: 12345
symbol: 37

所以在我看来,数组中的标量值是不同的。然而,这些标量指向的散列中的值是完全相同的。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:6)

1)您发布的代码在use strict;下不起作用,您的意思是%tempHash和%hash是否真的是同一个变量?

2)如果你使用%s而不是%p,你将获得3个相同的HASH(0x1234abcd)字符串,这意味着数组的内容确实是对同一个哈希的引用。

3)我建议每次都创建一个新的匿名哈希:

#!/usr/bin/perl -w
use strict;
use Data::Dumper;

my @array;
my %tempHash = (state => "apple", symbol => "54",memberId => "12345");
push(@array, { %tempHash });

%tempHash = (state => "tiger", symbol => "22", memberId => "12345");
push(@array, { %tempHash });

%tempHash = (state => "table", symbol => "37", memberId => "12345");
push(@array, { %tempHash });

print Dumper( \@array );

答案 1 :(得分:2)

听起来您使用Text::CSV从CSV文件中一次获取一行数据。

假设您的代码是这样的

my %tempHash;
my @array;

while (my $line = $csv->getline($fh)) {
  # Add values to %tempHash;
  push @array, \%tempHash;
}

然后您可以通过声明%tempHash insode while循环

来非常简单地解决您的问题
my @array;

while (my $line = $csv->getline($fh)) {
  my %tempHash;
  # Add values to %tempHash;
  push @array, \%tempHash;
}

因为每次输入块时Perl都会创建一个新的词法哈希


<强>更新

如果在每个输入记录之后数据不一定完整,则写入

my @array;
my $data = {};

while ( my $line = $csv->getline($fh) ) {
  # use information from $line to supplement $data
  if ($data is complete) {
    push @array, $data;
    $data = {};
  }
}

答案 2 :(得分:1)

如果您已将use strictuse warnings添加到tor脚本中,它会告诉您错误的内容:

1,填写哈希temphash并存储对它的引用。接下来你创建一个新的,hash,你填写但永远不会使用!相反,您要添加对temphash ...

的新引用

答案 3 :(得分:0)

我的赌注是push函数不关心引用。见perldoc

  

从Perl 5.14开始,push可以采用必须保持的标量EXPR   对未经处理的数组的引用。该论点将被解除引用   自动。推动的这个方面被认为是高度实验性的。   在未来的Perl版本中,确切的行为可能会发生变化。

修改

您可以尝试不使用push:

my @array;
my %tempHash = (state => "apple", symbol => "54", memberId => "12345");
$#array=4;
$array[0]=\%tempHash;
$array[1]=\%tempHash;
$array[2]=\%tempHash;
printf("%p %p %p\n", $array[0], $array[1], $array[2]);
foreach my $entry (@array){
    printf("state: %s\n", $entry->{state});
    printf("memberId: %s\n", $entry->{memberId});
    printf("symbol: %s\n\n", $entry->{symbol});
}

与我的perl口译员的结果相同,只是告诉我:-((perl 5.14.2)