Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

How do I compare 2 Arrays of Arrays and get a 3rd one? - updated -

by Miguel (Friar)
on Apr 02, 2004 at 00:38 UTC ( [id://341845]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings to all Monks,

I've been seraching for some help on how to compare and extract the differences between 2 Arrays of Arrays, but I'm totally lost in here.

My problem is:

I have 2 @AoA

my @A0A1 = ( [2003,1],[2003,3],[2003,4],[2004,1] ); my @A0A2 = ( [2003,1],[2003,2],[2003,3],[2003,4],[2003,5],[2003,6], [2003,7],[2003,8],[2003,9],[2003,10],[2003,11],[2003,12], [2004,1],[2004,2] );

Any help on how to compare these @A0As and get a 3rd one filled with the differences?
In this case would be something like this:

my @A0A3 = ( [2003,2],[2003,5],[2003,6],[2003,7],[2003,8], [2003,9],[2003,10],[2003,11],[2003,12],[2004,2] );
*** UPDATE ***

Esteemed Monks, thank you very much for your help.

Now, as I look and try your code, I'm asking myself if my problem could be solved in another way.

This is, the @AoA1 is always a subset of @A0A2, and values come from DB.

The @A0A2 values are calculated like this:

my $start_year = 2003; my $actual_year = 2004; my $actual_month = 3; while ( $start_year <= $actual_year ) { foreach ( my $i=1;$i<13;$i++ ) { if (( $actual_month > $i ) && ( $start_year == $actual_year )) { push @A0A2, [$start_year,$i]; } elsif ( $start_year != $actual_year ) { push @A0A2, [$start_year,$i]; } } $start_year++; }

This way i have a @A0A2 filled with Years and Months until a given month and a given year.

My question is: would be better to push and eliminate those values that exists on both @A0As while I'm _building_ the @A0A2? If so, how should I do that?

Thanks again for your patience.

Replies are listed 'Best First'.
Re: How do I compare 2 Arrays of Arrays and get a 3rd one?
by BrowserUk (Patriarch) on Apr 02, 2004 at 01:04 UTC

    Here's one approach. It assumes

    1. Your array values don't contain '|'.
    2. That the smaller array is a proper subset of the larger.

      If this is not the case it is a simple modification to add any elements from the smaller that do not appear in the larger...if that is your requirement.

    3. That you don't need the resultant set in any specific order.

      Again, it's a relatively trivial modification if you do need to retain the input order, though it raises a conflict with the resolution of 2) above.

    #! perl -slw use strict; use Data::Dumper; sub diffAoA{ my( $p, $q ) = @_; ( $p, $q ) = ( $q, $p ) if @$p < @$q; my %lookup = map{ join( '|', @$_ ), undef } @$p; delete @lookup{ map{ join( '|', @$_ ) } @$q }; return map{ [ split '\|' ] } keys %lookup; } my @A0A1 = ( [2003,1],[2003,3],[2003,4],[2004,1] ); my @A0A2 = ( [2003,1],[2003,2],[2003,3],[2003,4],[2003,5],[2003,6], [2003,7],[2003,8],[2003,9],[2003,10],[2003,11],[2003,12], [2004,1],[2004,2] ); my @diff = diffAoA \@A0A1, \@A0A2; print Dumper \@diff; __END__ P:\test>test3 $VAR1 = [ [ '2004', '2' ], [ '2003', '12' ], [ '2003', '5' ], [ '2003', '2' ], [ '2003', '9' ], [ '2003', '8' ], [ '2003', '11' ], [ '2003', '7' ], [ '2003', '10' ], [ '2003', '6' ] ];

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
Re: How do I compare 2 Arrays of Arrays and get a 3rd one?
by davido (Cardinal) on Apr 02, 2004 at 01:05 UTC
    This is an adaptation on an idea presented the Perl Cookbook (O'Reilly). Don't count on @diff being in any particular order though.

    use strict; use warnings; my @AOA1 = ( [2342, 1], [2444, 2], [3333, 3] ); my @AOA2 = ( [2444, 2], [3333, 3], [1234, 1] ); my @diff; { my %crossref; $crossref{ join "|", @{$_} }++ foreach ( @AOA1, @AOA2 ); foreach my $key ( keys %crossref ) { push @diff, [ split( /\|/, $key ) ] if $crossref{$key} < 2; } } print "@{$_}\n" for @diff;

    This assumes that "Difference" is defined as elements that are only found in one of the two arrays.

    Update: Fixed a typo in the split call.


    Dave

Re: How do I compare 2 Arrays of Arrays and get a 3rd one?
by DamnDirtyApe (Curate) on Apr 02, 2004 at 02:05 UTC

    And for the pseudo-official take on the problem:

    perldoc -q intersection

    _______________
    DamnDirtyApe
    Those who know that they are profound strive for clarity. Those who
    would like to seem profound to the crowd strive for obscurity.
                --Friedrich Nietzsche
      A link :-)

      --
      Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho

Re: How do I compare 2 Arrays of Arrays and get a 3rd one?
by Enlil (Parson) on Apr 02, 2004 at 01:31 UTC
    A slightly different approach:
    use strict; use warnings; use Data::Dumper; my @AOA1 = ( [2003,1],[2003,3],[2003,4],[2004,1] ); my @AOA2 = ( [2003,1],[2003,2],[2003,3],[2003,4],[2003,5],[2003,6], [2003,7],[2003,8],[2003,9],[2003,10],[2003,11],[2003,12], [2004,1],[2004,2] ); my @diff = diff_AoA(\@AOA1, \@AOA2); print Dumper \@diff; sub diff_AoA { my @AofArray_refs = @_; my %seen; foreach my $array_ref( @AofArray_refs ) { foreach my $array ( @$array_ref ){ my $key = join (",", map { qq("$_") } @$array ); $seen{$key}{COUNT}++; $seen{$key}{ARRAY_REF} = [ @$array ]; } } my @diff_array; foreach my $key ( keys %seen ) { push @diff_array, $seen{$key}{ARRAY_REF} if $seen{$key}{COUNT} < 2; } return @diff_array; };
    Note that this does not guarantee any sort of order, though that should be trivial to implement.

    -enlil

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-25 06:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found