ohcamel
ohcamel

Reputation: 319

Perl merging results of maps

How do I concatenate the output of two maps to form a single flat array?

I was attempting to use this:

my $test = { 'foo' => [
    map { 
        { 'i' => "$_" } 
    } 0..1,
    map {
        { 'j' => "$_" }
    } 0..1
] };

To achieve the result of this:

my $test = {'foo' => [
        {
            'i' => '0'
        },
        {
            'i' => '1'
        },
        {
            'j' => '0'
        },
        {
            'j' => '1'
        },
    ]}

However, this is what I got in $test instead:

{
    'foo' => [
        {
            'i' => '0'
        },
        {
            'i' => '1'
        },
        {
            'i' => 'HASH(0x7f90ad19cd30)'
        },
        {
            'i' => 'HASH(0x7f90ae200908)'
        }
    ]
};

Looks like the result of the second map gets iterated over by the first map.

Upvotes: 1

Views: 146

Answers (1)

zdim
zdim

Reputation: 66954

The list returned by the second map is a part of the input list for the first one, following 0..1,.

The parenthesis can fix that

use warnings;
use strict;

use Data::Dump;

my $test = { 
    'foo' => [ 
        ( map { { i => $_ } } 0..1 ),
        ( map { { j => $_ } } 0..1 )
    ],  
};

dd($test);

since they delimit the expression so now the first map takes only 0..1 as its input list and computes and returns a list, which is then merged with the second map's returned list. (Strictly speaking you need parenthesis only around the first map.)

This prints

{ foo => [{ i => 0 }, { i => 1 }, { j => 0 }, { j => 1 }] }

I've removed unneeded quotes, please restore them if/as needed in your application.

Without parenthesis the map after the comma is taken to be a part of the expression generating the input list for the first map, so producing the next element(s) of the input list after 0..1, effectively

map { i => $_ } (0..1, LIST);

Consider

my @arr = (
    map { { 'i', $_ } } 
        0..1, 
        qw(a b),
        map { ( { 'j', $_ } ) } 0..1
);
dd(\@arr);

It prints

[
  { i => 0 },
  { i => 1 },
  { i => "a" },
  { i => "b" },
  { i => { j => 0 } },
  { i => { j => 1 } },
]

This is also seen from your output, where all keys are i (no js).

Upvotes: 4

Related Questions