【问题标题】:How can I idiomatically access the first element of a single element hash in Perl?如何在 Perl 中惯用地访问单个元素哈希的第一个元素?
【发布时间】:2012-07-06 17:56:18
【问题描述】:

我有一个使用 DBI 的 fetchall_hashref() 获取一些数据的脚本。

通常它返回一个哈希引用,如下所示:

{ 1 => { id => 1 } }

但是,我只对哈希中第一项的值感兴趣,它是特定列的最大值。我知道 Perl 哈希没有排序,但幸运的是这个特定的查询总是返回 1 或 0 条记录(因为这是一个 MAX() 查询)。

但是目前用来实现的代码真的很丑:

$results->{(keys %{$results})[0]}->{'id'};

有没有更优雅的方式来激活它? (不借助 CPAN 模块)

澄清

我从我们内部使用的数据访问层获取哈希值。一切都通过 fetchall_hashref() 返回。我不调用 fetchall_hashref() 本身,它只是内部实现数据访问函数的方式,所以有人告诉我。我是该返回数据的消费者,它恰好是散列的形式。我正在寻找一种更简洁的方式(如果存在)来访问单个返回值查询的结果

【问题讨论】:

    标签: perl hash


    【解决方案1】:

    您可以取消引用%$results 中第一个值的id 键:

    (values %$results)[0]->{id};
    

    通常,这不会是well defined,因为the ordering of values returned keys or values can be different even between runs on the same machine using the same perl,但既然你说%$results 只能包含一个或零个元素,这是一个有效的方法。

    【讨论】:

    • 也可以扩展以获得第二个第一个值:(values %{(values %$results)[0]})[0]
    • (values %$results)[0]->{id}; 是完美的。它清楚地表明您对整个%$results 不感兴趣,只对它的值感兴趣。无需尝试为其添加更多 value
    • @fork0 您使用values 完成此任务并获得了第二名:D 但在可读性方面这是第一名。
    • 我试过了(值 %$results)[0]{id};似乎工作。剃掉两个字符。
    【解决方案2】:

    如果您只返回 0/1 行,为什么不使用 selectrow_arrayselectrow_hashref 而不是 fetchall_hashref?

    【讨论】:

    • 我是从我们内部使用的数据访问层获得的。一切都通过 fetchall_hashref() 返回。我不调用 fetchall_hashref() 本身,它只是内部实现数据访问函数的方式,所以有人告诉我。我是该格式的返回数据的消费者。我正在寻找一种更简洁的方法(如果存在)来访问单个返回值查询的结果。
    • 啊 - 您能否更新问题以说明使用 fetchall_hashref 是您访问数据的唯一方式
    【解决方案3】:

    您为什么使用fetchall_hashref 来获取单个值?最好使用selectrow_array

    my ($max) = $dbh->selectrow_array($sql);
    

    更新:如果您不能使用其他 DBI 方法,更简洁的方法是:

    my $val = [%$results]->[1]{id};
    

    【讨论】:

    • 有人能解释一下第二个表达式吗?正如@loldop 所说,它很漂亮,但[%$results] 到底是什么?
    • 我想我明白了:如果将哈希转换为列表,则由键和值对表示,其中只有值由其在列表中的索引获取。该操作产生的值是对另一个散列的符号引用,可用于通过简单的 {id} 运算符(Perl 魔术)访问散列值
    • 所以,虽然我的解决方案可能是“完美的” (@sinan-unur),但我个人会怀着热情记住这个 :)
    • @fork0:它是对包含%$results 的键/值对的数组的引用来自perldata:作为其他列表的一部分包含的哈希(...)总是扁平化为键/值对。
    • 非常聪明,@eugeney。向你致敬。但是,它几乎和原始代码一样晦涩难懂。尽管如此,Perl 高尔夫还是不错的。 ;-)
    【解决方案4】:

    您的数据访问层是否总是返回带有顺序键的散列?如果是,那又如何

    $results->{1}{id}
    

    (当然,它可能不会...但是您的示例数据使用键 1 作为第一条记录,因此数据访问层可能使用确定性键。)

    【讨论】:

      【解决方案5】:
      my @keys = sort { $a <=> $b } keys %$results;
      my $first = $keys[0];
      $results->{$first}->{id};
      

      或者如果 $first = 1;

      $results->{1}->{id};
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-15
        • 2010-12-20
        • 2021-08-01
        相关资源
        最近更新 更多