【问题标题】:Obtaining a slice through an array of hash references in Perl通过 Perl 中的哈希引用数组获取切片
【发布时间】:2016-05-29 14:50:55
【问题描述】:

我有一个与 Perl 相关的问题,涉及复杂的数据结构。我在托管 Apache 的 Linux (Centos v5) 服务器上运行 5.8.8 版的 Perl。我正在询问一个 MS-SQL 数据库。我正在使用“DBI”Perl 模块。

我有一个 SQL 查询的结果表,编码为对哈希引用数组的引用。所以表中的每一行都是一个包含哈希引用的数组元素,使用 DBI 模块的“fetchrow_hashref”命令获得。每个哈希的键对应于列标题,值对应于该列标题下表格中的特定单元格。

我想做的是获取一个列数据数组。 DBI 文档中似乎描述了一些关于如何获取列数据的方法,但对我来说它们有点不透明,如果作为练习,一般来说知道如何通过哈希引用数组获取切片会很好了解 perl 引用/取消引用的工作原理。

所以,基本上,鉴于此:

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;

我如何得到这个数组?:

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

我试过了:

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

但这只会让我获得列中的第一个单元格(即包含一个元素“dave”的数组)。 必须有一种优雅的方式在一行中执行此操作 - 如果你们中的 perl 专家可以帮助我,我将不胜感激。

谢谢

CJ

【问题讨论】:

  • perl 5.8.8 已经很老了。您可能需要考虑更新它。
  • 谢谢 - 我很想更新它,但这不是我的决定!

标签: arrays perl tsql hash


【解决方案1】:

开始的几件事:

这不是你定义哈希的方式:

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

这行代码将一个哈希引用分配给一个哈希,结果是这样的结构:

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

可能不是你想要的。

要正确定义您的哈希值,请将大括号替换为圆括号:

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

始终启用严格模式和警告:

use strict;
use warnings; 

这会发现分配对哈希的引用的错误。

--

现在,真正的问题是“如何从数组中的哈希引用中提取特定键?”

答案与哈希引用不在数组中的方式完全相同:

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

唯一的不同之处在于您需要对数组应用此操作。对数组应用操作是 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

【讨论】:

  • 谢谢 - 辛苦了! (顺便说一句,我总是使用严格和警告, - 我发布的代码更像是一个简化的示例 sn-p 而不是实际的真实脚本。我发布它时有点着急,所以我忘记了括号约定!)
【解决方案2】:

如果你使用过use strict; use warnings;,你会得到:

在 "script" "line" 处找到偶数大小列表的参考

你想填充一个哈希,使用:

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

注意括号而不是大括号

然后,为了打印名字,使用:

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

【讨论】:

    【解决方案3】:

    [编辑: 已经回答,但我正在为TIMTOWDI-ness 补充这个]

    使用perl5.22.0,您还可以这样做:

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

    【讨论】:

      猜你喜欢
      • 2013-08-10
      • 2010-12-19
      • 2015-12-23
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 2011-04-16
      • 2016-06-06
      • 2018-02-25
      相关资源
      最近更新 更多