【问题标题】:Accessing JSON decoded into a HASH and an array of hash references访问解码为 HASH 和哈希引用数组的 JSON
【发布时间】:2016-10-17 03:48:36
【问题描述】:

鉴于以下转储程序输出,有没有办法遍历每个哈希以仅列出每个 results->id 记录下的项目?我希望能够说:

print $results{1342}{'domain'};

并让语句返回 testing11.com 作为结果。

我是否必须先通读所有 results 数组,然后使用 $results[$counter]{id} 访问其中的数据?我不确定如何继续。

$VAR1 = { 
          'end_time' => 1466017739,
          'options' => {
                         'hour_offset' => '00',
                         'timezone' => 'America/New_York'
                       },
          'field_headers' => {
                              'priority' => 'Priority',
                              'status' => 'Status',
                              'assignee_external_id' => 'Assignee external id',
                              'initially_assigned_at' => 'Initially assigned at'
                             },
          'results' => [
                         {
                           'priority' => 'High',
                           'status' => 'Open',
                           'domain' => 'testing11.com',
                           'generated_timestamp' => 1546547669,
                           'id' => 1342
                          },
                         {
                           'priority' => 'Low',
                           'status' => 'Open',
                           'domain' => 'testing22.com',
                           'generated_timestamp' => 1464567669,
                           'id' => 7062
                          },
                         {
                           'priority' => 'Low',
                           'status' => 'Closed',
                           'domain' => 'testing33.com',
                           'generated_timestamp' => 1464267669,
                           'id' => 432
                          }]
      }

【问题讨论】:

    标签: json perl data-structures hash perl-data-structures


    【解决方案1】:

    您的转储显示包含一个标量、两个 hashref 和一个 arrayref 的 hashref。 arrayref 具有元素的 hashrefs。如果要从中检索特定元素,则需要知道索引。

    $top_level->{results}->[0]->{domain};  # is 'testing11.com'
    $top_level->{results}->[0]->{status};  # is 'open'
    

    要遍历它,取消对数组的引用

    foreach my $result (@{ $top_level->{results} }) {
        print "$result->{id}\n";
    }
    

    或者您可以从所有 results 元素中获取特定键的值,例如 id

    my @ids = map { $_->{id} } @{ $top_level->{results} };
    say "@ids";
    

    打印

    1342 7062 432

    请注意,对于包含引用的嵌套结构,您也可以使用语法

    $top_level->{results}[0]{domain};  # is 'testing11.com'  
    

    -> 在下标之间是可选的,参见Using References in perlref 中的规则 3。

    当哈希键是字符串时,它们应该被引用

    $top_level->{'results'}[0]{'domain'};
    

    但是,语法快捷方式允许我们在裸词上省略引号。但是,如果{} 中除了裸词之外还有其他任何内容,它将被解释为表达式并评估。因此,如果有任何疑问,请使用引号。您希望始终使用一致的符号。

    资源:教程perlreftut,参考perlref 和数据结构说明书,perldsc


    stevieb 的回答中给出了直接的解决方案,创建反向查找。复制到这里供参考

    my $results = $VAR1->{results};
    
    my %by_ip = map {$_->{id} => $_} @$results;
    
    print "$by_ip{1342}->{domain}\n";
    

    【讨论】:

    • @Douglas 有点不确定您是否有更具体的需求,如果有,请告诉我。
    • 你用很多方法做得很好。您应该将我的哈希示例加入其中,因为这正是 OP 正在寻找的 :)
    • @stevieb 谢谢你的好话。我宁愿写一张便条,引导他们找到你的答案,我现在认为这正是他们所要求的。另一方面,这可能是多余的 - 有答案,希望他们现在已经涵盖了所有内容。
    • 我对这个网站的理解是尽可能提供最佳答案,恕我直言,当我需要搜索时,SO 对此很有用,所以不要羞于接受我的答案,尤其是当我告诉你 :P 就是说,我敢肯定,在不至少说明你已经这样做的情况下从其他人的答案中“窃取”答案是不受欢迎的,但这显然不是这里的情况
    • 你涵盖了很多角度,所以如果你想从我发布的内容中添加更多答案,我不同意。无论如何,社区将决定哪个答案更有效。对于讨论,我属于 perlmonks。仅供参考,我在这里
    【解决方案2】:

    您需要将内部的$results 数组转换为新的哈希:

    my $results = $VAR1->{results};
    
    my %modded = map {$_->{id} => $_} @$results;
    
    print "$modded{1342}->{domain}\n";
    

    输出:

    testing11.com
    

    对于@$results 中的每个哈希引用,获取id 键的值,将其设置为新哈希(%modded)中的新键,然后分配整个哈希引用我们正在处理那个编号键的值。

    【讨论】:

    • 啊,对,这很可能是 OP 的内容。我突然想到它可能需要一个新的数据结构,但后来我决定换一种方式。
    • 是的。过去我已经做过几种方法,这似乎最适合这种类型的结构
    • 是的,这是扭转局面的好方法。我的意思是,我决定对反向查找进行更多的总体解释。很好地阅读了这个问题:)。也许......称之为%by_id或类似的?
    • 顺便说一句,这些 cmets 的时间在过去一个小时左右对我来说有点有趣......我看到它们比时间戳显示的要晚很多。不知道为什么
    • 是的。我在 cmets 上遇到了一些“故障” :) 都是我的错。 %by_id 可能是一个更好的名字。
    【解决方案3】:

    为了完整起见,如果您使用最新的 perl (use v5.24;)、后缀取消引用(默认启用)和对引用别名 (use feature 'refalias';) 的实验性支持,那么您可以取消引用 @ 987654329@ 并将其分配给别名 (%data),然后您可以将其作为常规哈希访问:

    use v5.24 ;
    use feature 'refaliasing';
    
    my $VAR1 = [AS ABOVE] ;
    foreach \my %data ( $VAR1->{results}->@* ) { say $data{domain} };
    

    我喜欢这种用法(尽管此时它远非公认的“惯用语”),因为您调用解引用语法“一次”——无论是后缀形式还是传统形式——然后在不需要的地方得到一个数据结构在块内使用->

    当然,您可以通过复制到临时哈希中来做到这一点。但别名可以被视为“更高效和可读”(cf. Data::Alias)。


    更多参考资料

    【讨论】:

      猜你喜欢
      • 2011-12-29
      • 1970-01-01
      • 2012-05-14
      • 1970-01-01
      • 2011-06-29
      • 2013-03-22
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      相关资源
      最近更新 更多