Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Merging arrays

by Anonymous Monk
on Jun 27, 2013 at 19:17 UTC ( #1041080=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I am passing values to a sub routine and I need to merge these values into on data structure to have this at the end:
# What I would like to have at the end: $VAR2 = [ { '111' => 'acct1', }, { '222' => 'acct2', }, { '333' => 'acct3', }, { '444' => 'acct4', }, { '555' => 'acct5', }, { '888' => 'acct8', }, ];
But having issues trying, any help? Here is my trying code:
#/usr/bin/perl use strict; use warnings; use Data::Dumper; my @array = qw( 111 222 333 444 555 888 ); my @array2 = qw( acct1 acct2 acct3 acct4 acct4 acct5 acct8 ); merge( \@array, \@array2); sub merge { my $got1 = shift; my $got2 = shift; my $vals_1 = @{$got1}; my $vals_2 = @{$got2}; my %hash_of_data = ( @{$vals_1} => @{$vals_2}); print Dumper %hash_of_data; my %data; push @{$data{@{$vals_1}}}, @{$vals_2}; print Dumper %data; #foreach my $k (keys %hash_of_data) { # foreach (@{$hash_of_data{$k}}) { # print " : $_\n"; # } # print "\n"; #} }
Thanks for looking!

Comment on Merging arrays
Select or Download Code
Re: Merging arrays
by Anonymous Monk on Jun 27, 2013 at 19:22 UTC

    If you don't mind consuming them:

    while( @input1 and @input2) { push @output, {(shift @input1), (shift @input2)}; }
Re: Merging arrays
by smls (Friar) on Jun 27, 2013 at 19:57 UTC

    The mesh function from the List::MoreUtils module can be used to create a hash out of two arrays, with the n'th values from the two arrays forming the n'th key/value pair in the hash:

    use List::MoreUtils qw(mesh); my @array = qw( 111 222 333 444 555 888 ); my @array2 = qw( acct1 acct2 acct3 acct4 acct5 acct8 ); my %merged = mesh @array, @array2;
Re: Merging arrays
by jeffa (Chancellor) on Jun 27, 2013 at 20:00 UTC

    I am going to assume you have a typo in your second array definition (repeated 'acct4'). If that is a mistake then just use a hash slice:

    my @array = qw( 111 222 333 444 555 888 ); my @array2 = qw( acct1 acct2 acct3 acct4 acct5 acct8 ); my %hash; @hash{@array} = @array2; use Data::Dumper; print Dumper \%hash;


    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      I am going to assume you have a typo in your second array definition

      Good point.
      If the double "acct4" item in the original code is not a typo but rather intended to demonstrate special handling for duplicate entries, then the OP would need to explain how exactly such cases should be handled.

      One possibility would be to strip all duplicate items from the list before merging (e.g. using the uniq function from List::MoreUtils). However, whether that is the correct thing to do would depend on the exact specification of the intended outcome in the general case.

Re: Merging arrays
by AnomalousMonk (Monsignor) on Jun 27, 2013 at 21:30 UTC

    The OP seems to want an array of hashes as output. Both smls's solution here and jeffa's here produce 'ordinary' hashes. Anonymous Monk's solution here produces an AoH, but, as stated, consumes the input arrays. Here's a solution producing an AoH without consuming the input arrays (presumed  'acct4' tyop noted by jeffa corrected):

    >perl -wMstrict -MData::Dump -le "my @array = qw( 111 222 333 444 555 888); my @array2 = qw(acct1 acct2 acct3 acct4 acct5 acct8); ;; sub blesh { my ($ar_1, $ar_2) = @_; ;; die qq{referenced arrays not same size} unless @$ar_1 == @$ar_2; ;; return map +{ $ar_1->[$_] => $ar_2->[$_] }, 0 .. $#$ar_1; } ;; my @AoH = blesh(\@array, \@array2); dd \@AoH; " [ { 111 => "acct1" }, { 222 => "acct2" }, { 333 => "acct3" }, { 444 => "acct4" }, { 555 => "acct5" }, { 888 => "acct8" }, ]

    Update: The odd-looking  +{ ... } in the map expression serves to disambiguate the  { ... } as an anonymous hash reference constructor rather than a subroutine block. The statement
        return map { { $ar_1->[$_] => $ar_2->[$_] } } 0 .. $#$ar_1;
    serves just as well (but note there is now no  , (comma) between the outermost terminating  } and the following 0).

Re: Merging arrays
by kcott (Abbot) on Jun 27, 2013 at 21:53 UTC

    This code produces the output you want:

    $ perl -Mstrict -Mwarnings -E ' use List::MoreUtils qw{pairwise}; $a || $b || 1; use Data::Dumper; my @array = qw( 111 222 333 444 555 888 ); my @array2 = qw( acct1 acct2 acct3 acct4 acct5 acct8 ); my $data = [ pairwise { +{ $a => $b } } @array, @array2 ]; print Dumper $data; ' $VAR1 = [ { '111' => 'acct1' }, { '222' => 'acct2' }, { '333' => 'acct3' }, { '444' => 'acct4' }, { '555' => 'acct5' }, { '888' => 'acct8' } ];

    Notes on my code:

    • I've excluded the duplicate acct4 (noted earlier by jeffa).
    • See List::MoreUtils for details on pairwise().
    • $a || $b || 1; stops "used only once" warnings for both $a and $b. Another way to do this would be with no warnings 'once'; but that's less specific and could potentially mask other, unrelated problems (see perllexwarn).
    • The + in front of { $a => $b } indicates to perl that this is a hashref — without it, perl interprets { $a => $b } as an anonymous block.

    Notes on your code:

    • In scalar context, @some_array evaluates to the number of elements in @some_array, so my $vals_1 = @{$got1}; will result in $vals_1 having a value of 6 (ditto for $vals_2). This would have resulted in messages about trying to use 6 as an array reference. (It would have been better if you had shown your error messages rather than just saying "... having issues ...".)
    • The output you say you want ($VAR2 = [ ... ];) is an arrayref; however, your code is populating hashes. Take a look at the Perl Data Structures Cookbook. If the output that you indicated you wanted is not correct, please clarify what you do want.
    • In the context of your code, where you use print Dumper %data; you probably want print Dumper \%data; (ditto for print Dumper %hash_of_data;). Take a look at Data::Dumper.

    -- Ken

Re: Merging arrays
by LanX (Canon) on Jun 27, 2013 at 22:53 UTC
    TIMTOWTDI¹...

    ...your AoH w/o extra modules and complicated maps using a temporary hash-slice:

    DB<100> @array = qw( 111 222 333 444 555 888 ); => (111, 222, 333, 444, 555, 888) DB<101> @array2 = qw( acct1 acct2 acct3 acct4 acct5 acct8 ); => ("acct1", "acct2", "acct3", "acct4", "acct5", "acct8") DB<102> @temp{@array}=@array2 => ("acct1", "acct2", "acct3", "acct4", "acct5", "acct8") DB<103> @AoH = map { { $_ => $temp{$_} } } @array => ( { 111 => "acct1" }, { 222 => "acct2" }, { 333 => "acct3" }, { 444 => "acct4" }, { 555 => "acct5" }, { 888 => "acct8" }, )

    (ignoring your typo)

    ¹) Note elements of @array must be unique ...

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      ... elements of @array must be unique...

      That strikes me as a drawback. After all, there seems to be nothing inherent in the organization of the two source arrays to suggest such a limitation. Why shouldn't one be allowed to end up with data like:

      my @AoH = ( { 111 => "acct1" }, { 111 => "hoo" }, { 111 => "ha" }, { 111 => "foo" }, { ... => "..." }, { 888 => "acct8" }, );
        > Why shouldn't one be allowed to end up with data like:

        No special reason.

        Sometimes one has data structure which have to be unique, then using a hash is handy.

        Sometimes not ... I'm just listing another way to do it for one of those loosely defined PM requirements... :)

        FWIW I'll change my post to make the restriction clearer ...

        update

        The question is rather how to design functional constructs like map which can easily (idiomatically) be used/combined to create nested data-structures which solve all possible requirements (sorted, nested, unique, non-string keys, ...).

        Thats more a design than an implementation question, I rarely see people using List::MoreUtils here.

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1041080]
Approved by johngg
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (11)
As of 2014-07-28 11:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (196 votes), past polls