Can I avoid links + dereferencing the hash returned from a card operation?

I have an array of hashes. I want the list of values ​​in the key of these 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 to return from map , but Perl won't have it:

Argument type 1 for values ​​must be a hash (not a map iterator) in script \ workbench.pl line 55, next to "@obs;"

+4
source share
2 answers

The problem is that values really, really wants the hash to work. This is because it is special: it cleans the seat holder used by each . This requires an actual object.

Here you can go in one of two ways. Firstly, if you don't like ref / deref, you can just pull the temporary hash from the single-line (choose your best code instead of %h ):

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

If you don't want %h hang, just put it in a temporary block:

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

Another approach might be to imitate what your temporary hash and values :

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

What really matters is what you are going to do with this data. If you just need your inverted hash values ​​only once, then your single-line scanner might be the best solution. If you need this data (id and value) later, then create the actual hash and use it - do not do this conversion more than once so that you can save them as single-line ones.

Without further context, it is difficult to give advice on which approach to take.

+7
source

If values was supposed to work on a list, it would take every second element of that list. So

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

will be

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

Now it is quite possible to write such a function, but in this case it is simply not needed. Can just do

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

And it simplifies

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

One catch: without using a hash, you are not eliminating duplicates.

0
source

Source: https://habr.com/ru/post/1346819/


All Articles