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

I tried figuring this out and have absolutely no idea. I looked at "Mastering Algorithms with Perl" but quickly got lost in the "Searching" chapter.

There are two data structures that are returned from DBI->fetchall_arrayref

I want to compare the arrays in both structures against each other and match on a specific element in the array, in this case the third element. All the arrays that match I want to store into a new data structure

Here is as far as I got, I need help with the subroutine:

#!/usr/bin/perl -w use strict; use Data::Dumper; # Array Reference my @array1 = ( ["a", "b", "match"], ["c", "d", "e"], ["f", "g", "h"], ["i", "j", "k"], ); my @array2 = ( ["l", "m", "z"], ["n", "o", "p"], ["q", "r", "s"], ["t", "u", "match"], ); # Make data structure similar to DBI's ->fetchall_arrayref; my $array_ref1 = \@array1; my $array_ref2 = \@array2; # Pass in data structures and define # which element to match against. my @matchedLists = &commonLists( \$array_ref1, \$array_ref2, 2 ); print Dumper \@matchedLists; sub commonLists { my ( $array_ref1, $array_ref2, $elementToMatch ) = @_; # Find the common lists where element $elementToMatch matches. # Result should return both lists that have "match" # in their third element. return \@match; }

Replies are listed 'Best First'.
Re: How to match specific elements of multiple array_references
by ikegami (Patriarch) on Jun 09, 2006 at 06:27 UTC

    Is there a reason you don't use the database to join these two arrays? If you can't, you could use the following:

    sub commonLists { my ( $array_ref1, $array_ref2, $elementToMatch ) = @_; my %lookup = map { $_->[$elementToMatch] => $_ } @$array_ref1; my @match; foreach my $fromArray2 (@$array_ref2) { my $fromArray1 = $lookup{$fromArray2->[$elementToMatch]}; push(@match, $fromArray1, $fromArray2) if $fromArray1; } return \@match; }

    Or if the field is not a key:

    sub commonLists { my ( $array_ref1, $array_ref2, $elementToMatch ) = @_; my %lookup; push(@{$lookup{$_->[$elementToMatch]}}, $_) foreach @$array_ref1; my @match; foreach my $fromArray2 (@$array_ref2) { my $fromArray1 = $lookup{$fromArray2->[$elementToMatch]}; push(@match, @$fromArray1, $fromArray2) if $fromArray1; } return \@match; }

    But it won't work until you fix the bug in your code.
    my @matchedLists = &commonLists( \$array_ref1, \$array_ref2, 2 );
    should be
    my @matchedLists = &commonLists( \@array1, \@array2, 2 );
    or
    my @matchedLists = &commonLists( $array_ref1, $array_ref2, 2 );

    Your variable naming stayle is inconsistent. You use both fooBar and foo_bar for similar things. Be consistent.

Re: How to match specific elements of multiple array_references
by ambrus (Abbot) on Jun 09, 2006 at 11:36 UTC
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @array1 = ( ["a", "b", "match"], ["c", "d", "e"], ["f", "g", "h"], ["i", "j", "k"], ); my @array2 = ( ["l", "m", "z"], ["n", "o", "p"], ["q", "r", "s"], ["t", "u", "match"], ); # Pass in data structures and define # which element to match against. my($matched1, $matched2) = common_lists(\@array1, \@array2, 2); print Data::Dumper->Dump([$matched1, $matched2], ["matched1", "matched +2"]); # Find the common lists where element $element_to_match matches. # Result should return both lists that have "match" # in their third element. sub common_lists { #don't mix camel-case and underscored words randomly my ($array_ref1, $array_ref2, $element_to_match) = @_; my(%index_first, $key, $array2); # For this, we build a hash of the elements to match from the firs +t # array of arrays. $index_first{${$$array_ref1[$_]}[$element_to_match]} = $_ for 0 .. @$array_ref1 - 1; # Then we iterate on the second array of arrays, for $array2 (@$array_ref2) { # extract the key from it, $key = $$array2[$element_to_match]; # check if that key is in the hash we've built, and if so exists($index_first{$key}) and # we return the corresponding array from the first array o +f arrays, # and the one from the second array of arrays as well. return $$array_ref1[$index_first{$key}], $array2; } } __END__

    Sorry, but I've adjusted your code a bit to my style.

    Output is:

    $matched1 = [ 'a', 'b', 'match' ]; $matched2 = [ 't', 'u', 'match' ];