如何在Perl中从数组中散列?
我想在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数据结构,则可以从使用Data :: Dumper进行打印以将其打印为人类可读(和Perl可分析)的形式中受益。
回答
数组中实际具有的是hashref,而不是哈希。如果我们不了解此概念,则可能值得阅读perlref文档。
得到你需要做的哈希
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之类的东西。
回答
哈希数组实际上并不包含哈希,而是对哈希的引用。
这行:
%row = $records[$index];
为%row分配一个条目。关键是标量:
{'id' => 1, 'firstName' => 'Jim'},
这是对哈希的引用,而值是空白。
我们真正想要做的是:
$row = $records[$index]; $row->{'firstName'};
要不然:
$row = %{$records[$index];} $row{'firstName'};
回答
其他人则对哈希与哈希引用进行了评论。我要提到的另一件事是DBQuery函数,看来我们正在尝试做一些已内置在DBI中的事情?如果我正确理解了问题,则我们正在尝试复制类似selectall_arrayref的内容:
This utility method combines "prepare", "execute" and "fetchall_arrayref" into a single call. It returns a reference to an array containing a reference to an array (or hash, see below) for each row of data fetched.
回答
要添加到上面可爱的答案中,让我补充说,我们应该始终,始终,始终(是,三个"总是"是)在代码顶部使用"使用警告"。如果这样做,我们将收到警告"参考在-e第1行找到了偶数大小的列表"。
回答
还请注意,要使用的一个很好的perl习惯用法是
for my $rowHR ( @records ) { my %row = %$rowHR; #or whatever... }
遍历列表。