in reply to Merging two array(refs)

Let me try to be more clear on what I mean:

in the following arrays qw/name pos loc age/ and qw/car dog age/ the "age" field is present in the first array already, so I don't want to add it again, I want to add the in the "age" (=last) position in the second array to the already existing "age" position in the final combined arref..

I hope that explains it a bit.

I can post the code I built up which doesn't look nice, though it does the job.. I'd prefer to have something nicer if possible

my $arr = [[qw/name pos loc age/], [qw/ike boss 12 44/], [qw/mat slave 22 21/], [qw/jill sec 15 32/],]; my $add = [[qw/car dog age/], [qw/a1 grr 3/], [qw/s2 miew 7/],]; my ($arrfld,$addfld); for ($i=0;$i<@{$arr->[0]};$i++){ $arrfld->{ $arr->[0]->[$i] } = $i } for ($i=0;$i<@{$add->[0]};$i++){ unless ( $arrfld->{ $add->[0]->[$i] } ){ $arrfld->{ $add->[0]->[$i] } = scalar(keys %$arrfld); } $addfld->{ $arrfld->{ $add->[0]->[$i] } } = $i; } foreach my $row (@$arr){ for($x=scalar(@$row);$x<scalar(keys %$arrfld);$x++){push @$row,""} } shift @$add; foreach my $row (@$add){ my $nr; for ($x=0;$x<scalar(keys %$arrfld);$x++){ $nr->[$x] = defined($addfld->{$x})?$row->[$addfld->{$x}]:""; } push @$arr,$nr; }

Replies are listed 'Best First'.
Re^2: Merging two array(refs)
by choroba (Cardinal) on Jan 21, 2013 at 01:17 UTC
    Note that you replied to yourself instead of replying to me. Therefore, I did not notice your reply immediately.

    Your code does not do what you claim. No arrays get merged when I run it. Please try to give more details: should the arrays be merged only if the last member is the same, or if any member is the same (i.e., should the script merge qw/a b key c/ with qw/x key y z/)? What would you do if more than one array from the second list could be merged into an array from the first one (i.e. both qw/car dog age/ and qw/train cat age/ in the second list)?

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      I've been staring at the screen for too long..

      It's funny you say it doesn't merge, I've just copied the code from the post and used Data::Dumper to dump $arr at the end and I can see it merged as it should be..

      No, the initial position of the member doesn't matter. If we look at an arbitrary first row of two arrefs:

      $a->[0] = [qw/f0 f1 f2 f3/]; $b->[0] = [qw/e0 f2 e1 f0 e2];
      If the value of the field in $b->[0] matches one already present in $a->[0] then all values in the matching field in the $b->1..$ arrays should be set in the already matched field. So the final array would be like:
      $m = [ [qw/f0 f1 f2 f3 e0 e1 e2], [qw/a0 a1 a2 a3 "" "" ""/],# ..and so on all of $a [qw/b3 "" b1 "" b0 b2 b4/],# ..and so on for $b->[1..$]
      a0,1,2.. being the first,second,third element of a $a->[x] array and likewise for the b0,1,2 of the $b->[x] array.

      Does this make it any clearer?

        Oh, wait, now I understand. The first member of the array is the header! I can see now what you mean by "merge", I imagined something different, which did not happen. I apologize for offending your code. Here is how I would do it. How sexy it is depends on the beholder's perspective:
        #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my $arr = [[qw/name pos loc age/], [qw/ike boss 12 44/], [qw/mat slave 22 21/], [qw/jill sec 15 32/],]; my $add = [[qw/car dog age/], [qw/a1 grr 3/], [qw/s2 miew 7/],]; my $i = 0; my %headers; for (@{ $arr->[0] }, @{ $add->[0] }) { $headers{$_} = $i unless exists $headers{$_}; $i++; } my $result = [ [ sort { $headers{$a} <=> $headers{$b} } keys %headers +] ]; my $new_columns = keys(%headers) - @{ $arr->[0] }; for (1 .. $#{$arr}) { push @$result, [ @{ $arr->[$_] }, (q()) x $new_columns ]; } my @rearranged = map $headers{$_}, @{ $add->[0] }; for my $row (1 .. $#{$add}) { my @new = (q()) x keys %headers; my $i = 0; $new[$_] = $add->[$row][$i++] for @rearranged; push $result, [@new]; } print Dumper $result;
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ