【问题标题】:Can I avoid referencing + dereferencing the hash returned from a map operation?我可以避免引用+取消引用从映射操作返回的哈希吗?
【发布时间】:2011-07-30 09:16:29
【问题描述】:

我有一个哈希数组。我想要一个基于另一个键的唯一性的哈希键中的值列表。

my @obs = ({
   value => 'three',
   id => 3
},{
   value => 'one-2',
   id => 1
},{
   value => 'one',
   id => 1
});
# This works, prints "one\nthree"
say for values %{{ map { $_->{id} => $_->{value} } @obs }};

我可以避免map 周围的引用+取消引用位吗?起初我尝试直接在从map 返回时调用values,但Perl 不会:

在 script\workbench.pl 第 55 行,“@obs ;”附近的 arg 1 到值的类型必须是散列(不是映射迭代器)

【问题讨论】:

    标签: perl idioms dereference


    【解决方案1】:

    问题是values 真的非常想要一个哈希来操作。那是因为它很特别:它清除了each 使用的占位符。它需要一个实际的对象来清除它。

    您可以在这里选择两种方式之一。首先,如果您不喜欢 ref/deref,您可以从单行中提取临时哈希的创建(请为您的实际代码选择一个比 %h 更好的名称):

    my %h = map { $_->{id} => $_->{value} }  @obs;
    say for values %h;
    

    如果您不希望 %h 闲逛,只需将其放入临时块中即可:

    ...code code code...
    {
        my %h = map { $_->{id} => $_->{value} }  @obs;
        say for values %h;
    }
    ...code code code...
    

    另一种方法可能是模拟您的临时哈希创建和values 正在做什么:

    my %seen;
    for ( reverse @obs ) { say $_->{value} unless $seen{$_->{id}}++ }
    

    真正重要的是您将如何处理这些数据。如果您只需要一次反向哈希的值,那么您的单线可能是最好的解决方案。如果您稍后需要此数据(id 和值),则创建实际的哈希并使用它 - 不要多次执行此转换,以便您可以将它们保留为单行。

    如果没有进一步的上下文,很难就采取哪种方法给出建议。

    【讨论】:

    • 我相信 David Golden 正在努力使 valueseachkeys 等内容在参考上起作用。它在 5.13(开发版本)中,应该在 5.14(生产版本)中。
    • @mpeters,由于运算符重载的歧义,存在一些争议,因此某些功能可能会在 5.14 中标记为实验性的。
    【解决方案2】:

    如果values 处理一个列表,它将占用该列表的每个第二个元素。所以

    say for values %{{ map { $_->{id} => $_->{value} } @obs }};
    

    say for every_odd map { $_->{id} => $_->{value} } @obs;
    

    现在,完全可以编写这样的函数,但在这种情况下根本不需要。一个人可以简单地做

    say for map { $_->{value} } @obs;
    

    这简化为

    say $_->{value} for @obs;
    

    一个问题:不使用散列,你不会消除重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-16
      • 2011-10-11
      • 2011-08-12
      • 2014-05-08
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多