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

Monks,

I've got two AoHs, and each hash shares a key, like so:

#!/usr/bin/perl use strict; use Data::Dumper; my @a = ({ domain => 'adomain.com', data => 'adata', }, { domain => 'bdomain.com', data => 'bdata', }); my @b = ({ domain => 'adomain.com', otherdata => 'astuff', }, { domain => 'bdomain.com', otherdata => 'bstuff', });

I want to end up with a single AoH that looks like this:

@c = ({ domain => 'adomain.com', otherdata => 'astuff', data => 'adata', }, { domain => 'bdomain.com', otherdata => 'bstuff', data => 'bdata', });

Just can't get my head around how to do this...

AH

----------
Using perl 5.8.1-RC3 unless otherwise noted. Apache/1.3.33 (Darwin) unless otherwise noted. Mac OS X 10.3.9 unless otherwise noted.

Replies are listed 'Best First'.
Re: combine two AoHs
by diotalevi (Canon) on Mar 06, 2006 at 22:37 UTC

    This merges the list of hashes by storing them temporarilly in the %merge hash and indexing them by 'domain'. You can omit the $to_merge temporary if you're willing to get a bit more ugly syntax.

    my @c = merge_aoh_by_domain( @a, @b ); sub merge_aoh_by_domain { my %merge; for my $domain_ref ( @_ ) { # less ugly my $to_merge = $merge{$domain_ref->{domain}} ||= {}; @$to_merge{ keys %$domain_ref } = values %$domain_ref; # ugly # @{$merge{$domain_ref->{domain}}{ keys %$domain_ref } = value +s %$domain_ref; } return values %merge; }

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: combine two AoHs
by ambrus (Abbot) on Mar 06, 2006 at 22:28 UTC
    @c = map { +{%{$a[$_]}, %{$b[$_]}} } 0 .. @a - 1;

    Update: it appears that I've interpreted your question differently from diotalevi. Here's an example on when they're different.

      Thanks to all three of you, but in particular ambrus, for demonstrating how the two methods differ.

      diotalevi gets bonus points for interpreting my poorly articulated question correctly ;-)

      AH

      ----------
      Using perl 5.8.1-RC3 unless otherwise noted. Apache/1.3.33 (Darwin) unless otherwise noted. Mac OS X 10.3.9 unless otherwise noted.
Re: combine two AoHs
by GrandFather (Saint) on Mar 06, 2006 at 22:51 UTC

    map and a little casting magic does the trick. Note the %{$a[$_]} that turns the hash ref returned by $a[$_] into a hash.

    BTW, you should perhaps avoid using a and b - even when they are not scalars they can cause confusion due to $a and $b being used for sort parameters. (Yes, I know this is a trivial sample, but good habits are good habits.)

    use strict; use warnings; use Data::Dump::Streamer; my @a_ = ({ domain => 'adomain.com', data => 'adata', }, { domain => 'bdomain.com', data => 'bdata', }); my @b_ = ({ domain => 'adomain.com', otherdata => 'astuff', }, { domain => 'bdomain.com', otherdata => 'bstuff', }); my @c = map {{%{$a_[$_]}, %{$b_[$_]}}} 0..$#a_; Dump (\@c);

    Prints:

    $ARRAY1 = [ { data => 'adata', domain => 'adomain.com', otherdata => 'astuff' }, { data => 'bdata', domain => 'bdomain.com', otherdata => 'bstuff' } ];

    DWIM is Perl's answer to Gödel