Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a two-layer hash, i.e.

$hash{ $key1 }{ $key2 } = $value;

I'd like to convert it into an array of hashes from the second layer. This is for JSON-style data, an "array of records". i.e.

@Array( \$hash{$key1}, ...)

My first attempt was writing nested foreach loops but I was creating @Array from scratch, with new anonymous hash references, so I was actually creating new copies of all the data in memory.

foreach $key1 (keys %hash) { foreach $key2 (keys %{$hash{$key1}}) { push(@Array, { key2_ => $hash{$key1}{$key2} }); }

How can I do this in code without having to create new copies of all the data? This hash is really big so I'm trying to be efficient. It seems like I should be able to just grab references to all the subkeys.

Something like this:

foreach $key1 (keys %hash) { push(@Array, \%{ $hash{$key1} }); }

I was trying to figure out how to do it with a map but couldn't seem to figure it out.

Replies are listed 'Best First'.
Re: Convert hash of hashes into array of hahes
by davido (Cardinal) on Mar 25, 2014 at 17:37 UTC

    Instead of foreach, use each with while loops.

    Untested:

    while( my( $key1, $ref1 ) = each %hash ) { while( my( $key2, $val2 ) = each %{$ref1} ) { push @Array, { $key2 => $val2 }; } }

    Using keys in list context as the expression for a foreach loop is generating a list internally of all of the outer keys, and lists of inner keys. Switching to the while loop saves at least that much.


    Dave