如何在Perl中从数组中散列?

时间:2020-03-05 18:49:49  来源:igfitidea点击:

我想在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进行打印以将其打印为人类可读(和Per​​l可分析)的形式中受益。

回答

数组中实际具有的是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...
}

遍历列表。