2

If there's a hash where one of the values is an array, what's the shortest way to split into an array-of-hashes (AoH) for each array value that keeps all the hash keys and values, except for replacing the original array with individual values?

The following illustrates the functional goal, but I feel like there's some map or similar magic that could do this as a one-liner.

use strict;
use warnings;
use Data::Dumper;

my @result;

my %hash = (
    a => "string",
    b => [ "13", "14", "15" ],
    c => "another string",
);

foreach my $b (@{$hash{'b'}}) {
    push @result, { %hash };
    $result[-1]{'b'} = $b;
}

print Dumper(\@result);

Desired outcome:

$VAR1 = [
          {
            'b' => '13',
            'a' => 'string',
            'c' => 'another string'
          },
          {
            'c' => 'another string',
            'a' => 'string',
            'b' => '14'
          },
          {
            'b' => '15',
            'c' => 'another string',
            'a' => 'string'
          }
        ];
0

2 Answers 2

5

You are correct, you can use map to do this by mapping over the b values, also instead of editing the thing you just pushed, construct the new hashes with the modified b values:

use strict;
use warnings;
use Data::Dumper;

my %hash = (
    a => "string",
    b => [ "13", "14", "15" ],
    c => "another string",
);

my @result = map {
  +{
    %hash,
    b => $_
  }
} @{$hash{b}};

print Dumper(\@result);
Sign up to request clarification or add additional context in comments.

2 Comments

0

It's not that short, but a generic solution.

use strict;
use warnings;
use Data::Dumper;

my %hash = (
    a => "string",
    b => [ "13", "14", "15" ],
    c => "another string",
);

use List::Util 1.39 qw(pairs reduce);

my @result = map @$_, reduce { [
    map {
        my @a = %$_;
        map {
            +{ @a, $b->key => $_ }
        } ref $b->value ? @{$b->value} : $b->value;
    } @$a
] } [ +{} ], pairs %hash;

print Dumper \@result;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.