Can I return a few pairs from a hash card?

I am trying to create a hash that is looking for a key or value. To search in both directions, I want the values ​​to be keys (with the values ​​that are their keys).

< H He > ==> map( { state $n = 0; $n++; $n => $_.Str, $_.Str => $n } ) ==> my %elements; %elements.perl.say; %elements{2}.WHAT.say; 

This gives me this weird thing:

 {"1\tH H\t2" => $(2 => "He", :He(2))} (Any) 

With just one pair, this is normal:

 < H He > ==> map( { state $n = 0; $n++; $n => $_.Str } ) ==> my %elements; %elements.perl.say; %elements{2}.WHAT.say; 

Now I get what I want, but without the inverse pair:

 {"1" => "H", "2" => "He"} (Str) 
+6
source share
1 answer

Your map returns a sequence of List values, each of which contains two Pair values.
Submitting this to the hash will not automatically smooth it, and each List becomes the key or hash value.

There are several ways to get it to do what you want:

Using flat

You can use the built-in flat function to smooth out the map result so that the hash gets the sequence Pair s

 <H He> ==> map { (state $n)++; +$n => ~$_, ~$_ => +$n }\ ==> flat() ==> my %elements; %elements.say; # {1 => H, 2 => He, H => 1, He => 2} %elements{2}.WHAT.say; # (Str) 

Both map and flat return lazy sequences, so this is (theoretically) memory efficient, even if the list of items is long.

  • Lateral note: I also wrote +$n instead of $n , because the build operator => Pair (for example, a list build operator) does not “deconstruct”, its arguments are if you give it a container of goods, such as the variable $ , it will be bound to it directly, and not to the value contained in it, which will lead to the fact that the next $n++ will also affect the Pair returned from the previous iteration. Providing the operator to construct a pair of expression values ​​instead of a variable avoids this.

Using slip

slip is the highest version of flat :

 <H He> ==> map { (state $n)++; slip +$n => ~$_, ~$_ => +$n }\ ==> my %elements; 

Each iteration of map now returns a value of type slip , which is similar to List , except that it automatically dissolves in any parent list, it becomes part.

Refactoring

If you're not tied to your particular approach, here are two potentially clearer ways to generate the same hash:

 my @keys = 1..*; my @values = <H He>; my %elements = flat (@keys Z=> @values), (@values Z=> @keys); 

Or:

 my %elements = 1..* Z=> <H He>; push %elements, %elements.invert; 

( Z is the meta-operator "zip")

+6
source

All Articles