如何在 Perl 中从数组中获取哈希值?
-
09-06-2019 - |
题
我想在 perl 中编写一个小的“DBQuery”函数,这样我就可以使用单行代码来发送 SQL 语句并接收返回的哈希值数组,即一个记录集。然而,我遇到了 Perl 语法的问题(可能还有一些奇怪的指针/引用问题),这阻止我从数据库获取的哈希中打包信息。下面的示例代码演示了该问题。
我可以使用以下语法从数组内的哈希中获取数据“Jim”:
print $records[$index]{'firstName'}
返回“吉姆”
但是如果我首先将数组中的哈希记录复制到它自己的哈希变量中,那么奇怪的是我无法再访问该哈希中的数据:
%row = $records[$index];
$row{'firstName'};
返回“”(空白)
这是显示问题的完整示例代码。任何帮助表示赞赏:
my @records = (
{'id' => 1, 'firstName' => 'Jim'},
{'id' => 2, 'firstName' => 'Joe'}
);
my @records2 = ();
$numberOfRecords = scalar(@records);
print "number of records: " . $numberOfRecords . "\n";
for(my $index=0; $index < $numberOfRecords; $index++) {
#works
print 'you can print the records like this: ' . $records[$index]{'firstName'} . "\n";
#does NOT work
%row = $records[$index];
print 'but not like this: ' . $row{'firstName'} . "\n";
}
解决方案
嵌套数据结构包含哈希 参考, ,不是哈希值。
# Will work (the -> dereferences the reference)
$row = $records[$index];
print "This will work: ", $row->{firstName}, "\n";
# This will also work, by promoting the hash reference into a hash
%row = %{ $records[$index] };
print "This will work: ", $row{firstName}, "\n";
如果您曾经遇到过深入的 Perl 数据结构,您可能会从使用以下命令打印它中受益 数据::转储器 将其打印为人类可读(和 Perl 可解析)的形式。
其他提示
哈希数组实际上并不包含哈希值,而是包含 参考 到一个哈希值。这行:
%row = $records[$index];
为 %row 分配一个条目。关键是 标量:
{'id' => 1, 'firstName' => 'Jim'},
这是对哈希值的引用,而值为空。
你真正想做的是:
$row = $records[$index];
$row->{'firstName'};
要不然:
$row = %{$records[$index];}
$row{'firstName'};
其他人对哈希与哈希引用发表了评论。我觉得应该提到的另一件事是你的 DBQuery 函数 - 看来你正在尝试做一些已经内置到 DBI 中的事情?如果我正确理解你的问题,你正在尝试复制类似的东西 selectall_arrayref:
该实用方法将“prepare”、“execute”和“fetchall_arrayref”组合到一个调用中。它返回对数组的引用,其中包含对所获取的每行数据的数组(或散列,见下文)的引用。
为了补充上面可爱的答案,让我补充一点,你应该总是,总是,总是(是的,三个“总是”)在代码顶部使用“使用警告”。如果您这样做了,您将收到警告“在 -e 第 1 行预期的偶数大小列表中找到了参考”。
您的数组中实际拥有的是 hashref,而不是哈希。如果您不理解这个概念,可能值得阅读 佩尔参考 文档。
得到你需要做的哈希
my %hash = %{@records[$index]};
例如。
my @records = (
{'id' => 1, 'firstName' => 'Jim'},
{'id' => 2, 'firstName' => 'Joe'}
);
my %hash = %{$records[1]};
print $hash{id}."\n";
虽然。我不确定你为什么要这样做,除非是出于学术目的。否则,我建议在 DBI 模块中使用 fetchall_hashref/fetchall_arrayref 或使用 Class::DBI 之类的东西。
另请注意,一个好的 Perl 习惯用法是
for my $rowHR ( @records ) { my %row = %$rowHR; #or whatever... }
迭代列表。