9

I have a list of two-element lists, like what you'd get for example by (1..5) Z (20..24), that I want to make into a hash (in this example, what you get by {1 => 20, 2 => 21, 3 => 22, 4 => 23, 5 =>24}. I could do it "by hand", but that isn't too elegant, and I'm sure Raku has a idiomatic way of doing it. The inelegant alternative I come up with is:

my @a = (1..5) Z (20..24);
my %a;
for @a -> @x {
   %a{@x[0]} = @x[1];
Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
vonbrand
  • 11,412
  • 8
  • 32
  • 52

1 Answers1

12
my %h = (1..5) Z=> (20..24);
say %h;  # {1 => 20, 2 => 21, 3 => 22, 4 => 23, 5 => 24}

The Z meta-operator takes an operator as part of its name, and it defaults to ,, thus creating lists by default. If you add the Pair constructor (aka fat-comma), then you create a list of Pairs, which you can feed into a Hash.

An alternate solution would be to flatten the result of Z:

my %h = flat (1..5) Z (20..24);
Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
  • 1
    For this particular example, this works fine. But what if I got the list of two-element lists somehow else? – vonbrand Mar 28 '20 at 21:21
  • 1
    @vonbrand The flattening strategy is fully general. `flat` will flatten multiple levels of a multi-level data structure if the levels are `List`s. But if you've already introduced non-`List`s, eg assigning the data to an `Array` without using `flat` *before* doing so, then `flat` will no longer be the right tool. For example, if you've assigned it using `my @a = 1..5 Z 20..25;` then `flat` alone won't do the job. I would flatten it like this `my %h = @a[*;*];`. I've written a bit more about using subscripts to flatten out multi-level data [here](https://stackoverflow.com/a/37230217/1077672). – raiph Mar 28 '20 at 22:49
  • @ralph, what about `((1, (1, 2, 3)), (2, (5, 6)), (17, (3, 4, 5, 92, 31))` (i.e., the end result would be a hash with lists as values)? – vonbrand Mar 29 '20 at 01:30