简体   繁体   English

通过Perl中的哈希引用数组获取切片

[英]Obtaining a slice through an array of hash references in Perl

I have a Perl-related question, concerning complex data structures. 关于复杂的数据结构,我有一个与Perl相关的问题。 I am running version 5.8.8 of Perl on a Linux (Centos v5) server, hosting Apache. 我在托管Apache的Linux(Centos v5)服务器上运行Perl版本5.8.8。 I am interrogating a MS-SQL database. 我正在询问MS-SQL数据库。 I am using the "DBI" Perl module. 我正在使用“DBI”Perl模块。

I have a table of results from an SQL query, encoded as a reference to an array of hash references. 我有一个SQL查询结果表,编码为对哈希引用数组的引用。 So each row in the table is an array element containing a hash reference, obtained using the "fetchrow_hashref" command of the DBI module. 因此,表中的每一行都是一个包含哈希引用的数组元素,使用DBI模块的“fetchrow_hashref”命令获得。 The keys of each hash correspond to the column headings and the values corresponding to a particular cell in the table under that column heading. 每个散列的键对应于列标题和对应于该列标题下的表中的特定单元格的值。

What I would like to do is to obtain an array of column data. 我想要做的是获得一列列数据。 There appear to be some methods described in the DBI documentation about how to obtain column data, but to me they are a little opaque, and it would be nice to know in general how to obtain a slice through an array of hash references as an exercise in understanding how perl referencing / dereferencing works. 似乎在DBI文档中描述了一些关于如何获取列数据的方法,但对我来说它们有点不透明,一般都知道如何通过一组哈希引用获取切片作为练习了解perl引用/解除引用的工作原理。

So, basically, given this: 所以,基本上,鉴于此:

my %datarow1 = {"firstname"=> "dave", "bar"=>"smith"};
my %datarow2 = {"firstname"=> "john", "bar"=>"doe"};
my %datarow3 = {"firstname"=> "kim", "bar"=>"kardashian"};

Referenced like this: 引用如下:

my @rows = (\%datarow1, \%datarow2, \%datarow3);
my $rowsref=\@rows;

How do I get this array?: 我怎么得到这个数组?:

("dave", "john", "kim")

I've tried this: 我试过这个:

my @columndata=@$rowsref->[0]{"firstname"}

but this only gets me the first cell in the column (ie an array containing the one element "dave"). 但这只能让我获得列中的第一个单元格(即包含一个元素“dave”的数组)。 There must be an elegant way of doing this in one line - if on of you perl gurus could help me out, I'd appreciate it hugely. 必须有一种优雅的方式在一行中做到这一点 - 如果你的perl大师可以帮助我,我会非常感激。

Thanks 谢谢

CJ CJ

A few things to start: 一些事情要开始:

This is not how you define a Hash: 这不是你定义哈希的方式:

my %datarow1 = {"firstname"=> "dave", "bar"=>"smith"};

this line of code assigns a Hash reference to a Hash, which results in a structure like this: 这行代码将哈希引用分配给哈希,这会产生如下结构:

( 'HASH(0x7f4ef0545e18)' => undef )

probably not what you wanted. 可能不是你想要的。

To define your hashes correctly replace the curly braces with parentheses: 要正确定义哈希,请用括号替换花括号:

my %datarow1 = ("firstname"=> "dave", "bar"=>"smith");

Always enable strict mode and warnings: 始终启用严格模式和警告:

use strict;
use warnings; 

this would have caught the mistake of assigned a reference to a Hash. 这会错误地分配对哈希的引用。

-- -

Now, the real question is "How do I extract a specific key from Hash references held in an array?" 现在,真正的问题是“如何从数组中保存的哈希引用中提取特定键?”

and the answer is exactly the same way as if the Hash references were not in an array: 答案与Hash引用不在数组中的方式完全相同:

my $h_ref = { a => b };
# get key 'a'
my $a = $h_ref->{a}; 

the only difference is that you need to apply this operation over an array. 唯一的区别是您需要在数组上应用此操作。 Applying operations over arrays is the purpose of the map builtin: 在数组上应用操作是内置map的目的:

use strict;
use warnings; 

my %datarow1 = ("firstname"=> "dave", "bar"=>"smith");
my %datarow2 = ("firstname"=> "john", "bar"=>"doe");
my %datarow3 = ("firstname"=> "kim", "bar"=>"kardashian");

my @rows = (\%datarow1, \%datarow2, \%datarow3);
my $rowsref=\@rows;
my @firstnames = map { $_->{firstname} } @$rowsref; 
# dave john kim

If you've used use strict; use warnings; 如果你已经use strict; use warnings; use strict; use warnings; you'd get: 你会得到:

Reference found where even-sized list expected at "script" "line" 参考文献在“脚本”“行”处找到了偶数大小的列表

You want to populate a hash, use: 您想要填充哈希,使用:

my %datarow1 = ("firstname"=> "dave", "bar"=>"smith");

Note the parenthesis instead of curly brackets 请注意括号而不是大括号

Then, for printing the firstname, use: 然后,要打印名字,请使用:

my @columndata = map {$_->{"firstname"}}  @$rowsref;
say Dumper\@columndata;

[ Edit: already answered but I am ading this for TIMTOWDI -ness ] [ 编辑:已经回答,但我正在为TIMTOWDI ]

With perl5.22.0 you can also do: 使用perl5.22.0您还可以:

use experimental 'refaliasing';

for \my %hash (\%datarow2, \%datarow1, \%datarow3 ) { 
      say $hash{"firstname"} ; 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM