我可以避免引用+解除引用从地图操作返回的哈希吗?

时间:2011-04-05 22:38:38

标签: perl idioms dereference

我有一系列哈希。我希望根据另一个键的唯一性在这些哈希的键中列出值。

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周围的引用+解除引用位吗?起初我尝试直接从values返回时调用map,但Perl不会拥有它:

  

arg 1到值的类型必须是在脚本\ workbench.pl第55行的哈希(不是map迭代器),靠近“@obs;”

2 个答案:

答案 0 :(得分:7)

问题是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& value),则创建实际哈希并使用它 - 不要多次执行此转换,以便您可以将它们保持为单行。

如果没有进一步的背景,很难就哪种方法提出建议。

答案 1 :(得分:0)

如果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;

一个问题:通过不使用哈希,你不会消除重复。