0

我已经搜索和搜索,但我找不到任何我发现可以工作的代码。很抱歉,如果这是在重复旧的情况,但我现在花了 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

4 回答 4

6

1) The code you posted doesn't work under use strict;, did you mean %tempHash and %hash are really the same variable?

2) If you use %s instead of %p, you'll get 3 identical HASH(0x1234abcd) strings, which means the contents of the array are indeed references to the same hash.

3) I would suggest creating a new anonymous hash each time:

#!/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 );
于 2012-08-02T11:38:01.977 回答
2

听起来您正在使用Text::CSV.

假设你的代码是这样的

my %tempHash;
my @array;

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

那么你可以很简单地通过声明循环%tempHash来解决你的问题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 = {};
  }
}
于 2012-08-02T12:29:39.020 回答
1

如果您将use strictand添加use warnings到 tor 脚本,它会告诉您出了什么问题:

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

于 2012-08-02T11:32:55.490 回答
0

我敢打赌,推送功能并不关心引用。请参阅perldoc

从 Perl 5.14 开始, push 可以采用标量 EXPR,它必须包含对 unblessed 数组的引用。该参数将被自动取消引用。推送的这一方面被认为是高度实验性的。在 Perl 的未来版本中,确切的行为可能会改变。

编辑

您可以尝试不使用推送:

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)

于 2012-08-02T11:10:55.607 回答