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 ;"
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With