Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I avoid referencing + dereferencing the hash returned from a map operation?

I've got an array of hashes. I want the a list of the values in a key of those hashes based on the uniqueness of another key.

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 }};

Can I avoid the reference + dereference bit around the map? At first I tried just calling values directly on the return from map but Perl won't have it:

Type of arg 1 to values must be hash (not map iterator) at script\workbench.pl line 55, near "@obs ;"

like image 286
wes Avatar asked Apr 05 '11 22:04

wes


1 Answers

The problem is that values really, really wants a hash to operate on. That's because it's special: it clears the place holder used by each. It needs an actual object to clear that on.

You can go one of two ways here. First, if you don't like the ref/deref, you could just pull the creation of the temporary hash out of the one-liner (please pick a better name than %h for your actual code):

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

If you don't want %h to hang around, just drop it into a temporary block:

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

Another approach could be to emulate what your temporary hash creation and values is doing:

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

What really matters is what you're going to be doing with this data. If you just need the values of your inverted hash just once, then your one-liner may be the best solution. If you need this data (id & value) later on, then create the actual hash and use that -- don't do this transform more than once just so that you can keep them as one-liners.

Without further context, it's hard to give advice on which approach to take.

like image 119
unpythonic Avatar answered Nov 04 '22 22:11

unpythonic