Using a map to extract a hash set (key, value) matching a given value

I was looking for a way to do the following using the perl map function: I want to extract pairs (key, value) in which the value is equal to or matches the specified parameter.

In my example, I want to extract pairs (key, value), where value = failed , but can also be an expression (i.e. a line starting with A or REGEX). That's why I want the resulting hash, and not just a table of keys matching the value.

 my %strings = ( bla => "success", ble => "failed", bli => "failed", foo => "success", blo => "failed", bar => "failed", blu => "success" ); my %failed_s = (); while (my ($k, $v) = each %strings) { if ( $v eq 'failed' ) {$failed_s{$k} = $v}; }; 

I tried several ways to do this, but without great results, so I think I'm confused about links, affects, results, etc.

 my %failed_s = map { { $_ => $strings{$_} } if ( $strings{$_}./failed/ ) } keys %strings; my %failed_s = map { ( $strings{$_} eq 'failed') && ($_, $strings{$_}) } keys %strings; print "Dumper \%failed_s: \n" . Dumper(\%failed_s); 

In this case, it would be impossible or inefficient to use the card, but it would help me (and possibly others) find out why.

+6
source share
4 answers

In your first map example, you return hash links for a single element, which you don't want.

In its second, the && operator imposes a scalar context on its arguments, so the list ($_, $strings{$_}) returns only the last element in the list.

What are you looking for:

 my %failed_s = map { $strings{$_} eq 'failed' ? ($_, $strings{$_}) : () } keys %strings; 

If the operator ? : ? : returns a list if the condition is true, and an empty list if it is false.

+6
source

Perl has easy access to hashing logic to the point where few people have been able to distinguish the Key-Value Pair concept from its most common implementation: Hash.

So, when most Perlers think about KVP, they think “hash”. But think about how Perl Arrays: 1) lists, 2) queues and 3) stacks, and you will see that the implementation does not quite correspond to the concept.

I saw the need to process pairs in a mod outside of hashes, so I created my own library, which I wanted to load into CPAN until I found List::Pairwise already exists.

(Of course, it seems that I have no "hash splicing" methods ...)

Anyway, using List::Pairwise , you simply

 use List::Pairwise qw<grepp>; my %failed_s = grepp { $b eq 'failed' } %strings; 

I feel like an advertising guy when I say, "Just see how brief it is!"

+8
source

map FUNC, LIST works with every element in LIST. Your function may return an empty list for some elements (as suggested by Eric Strom's answer). Another approach is to use another filter, so map only works with the elements you are interested in:

 my %failed_s = map { $_ => $strings{$_} } grep { $strings{$_} eq 'failed' } keys %strings; 
+3
source

I think the map + grep combination is cleaner.

 my %failed_s = map { $_ => $strings{$_} } grep { $strings{$_} eq 'failed' } keys(%strings); 

But since grep can be implemented using a map,

 my %failed_s = map { $_ => $strings{$_} } map { $strings{$_} eq 'failed' ? $_ : () } keys(%strings); 

this can be done using only the card.

 my %failed_s = map { $strings{$_} eq 'failed' ? ($_ => $strings{$_}) : () } keys(%strings); 

You had a problem that you were returning false when you wanted to return nothing.

+3
source

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


All Articles