Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Comparing two arrays (was: any smart ideas??:)

by Anonymous Monk
on May 30, 2002 at 14:21 UTC ( [id://170390]=perlquestion: print w/replies, xml ) Need Help??

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

Hello! I'm quite new to perl, so forgive my silly(??!!) question!:)
I have to arrays, @array1 and @array2
foreach my $element(@array1) { #I want to check if the value exists in @array2 #Any smart ways to deal with this? #This looks bad... foreach my $another_element(@array2) { if ($element eq $another_element) { print "Hey...\n"; } } }

Edit kudra, 2002-05-31 Changed title

Thanks!:)

Replies are listed 'Best First'.
Re: any smart ideas??:)
by the_0ne (Pilgrim) on May 30, 2002 at 14:47 UTC
Re: any smart ideas??:)
by VSarkiss (Monsignor) on May 30, 2002 at 14:56 UTC

    What you're trying to do, essentially, is calculate set union and/or set difference (depending on how you look at it) using arrays.

    This is covered in Perl FAQ section 4. There are variations in the Perl Cookbook, and people have posted questions and code snippets here in the monastery. You can also snoop around the Categorized Questions and Answers. One of those should provide answers.

Re: any smart ideas??:)
by vladb (Vicar) on May 30, 2002 at 14:47 UTC
    Not a 'smart' way.. but here goes:
    use strict; my @a=qw(a b c d); my @b=qw(b a e f); # this does exactly what your pair of 'for' loops # did... my @m = map { my $x = $_; grep { /^$x$/ } @b; } @a; print @m; print "\n";
    Prints output:
    ab


    UPDATE 1: A slightly 'smarter' alternative here ;)
    use strict; my @a=qw(a b c d); my @b=qw(b a e f); my %h; my @m = map {$h{$_}++ ? $_ : ()} (@a, @b); print @m; print "\n";
    This time, I'm using a hash to keep count of number of tiems a value is found in both arrays. For any value that's been counted more than once, I dump it into the @m array.

    _____________________
    $"=q;grep;;$,=q"grep";for(`find . -name ".saves*~"`){s;$/;;;/(.*-(\d+) +-.*)$/; $_=["ps -e -o pid | "," $2 | "," -v "," "];`@$_`?{print"+ $1"}:{print" +- $1"}&&`rm $1`; print$\;}
Re: any smart ideas??:)
by DamnDirtyApe (Curate) on May 30, 2002 at 15:17 UTC

    Not to try and throw you in over your head, but if the context of your program is more related to set operations than to array properties, you may want to have a look at Set::Scalar. This module will allow you do something as simple as:

    use Set::Scalar ; my $s = Set::Scalar->new( 'a', 'b', 'c', 'd' ) ; my $t = Set::Scalar->new( 'a', 'e', 'c', 'o' ) ; my $u = $s->intersection( $t ) ; print $u, "\n" ;
    And the output:
    (a c)

    _______________
    D a m n D i r t y A p e
    Home Node | Email
Re: any smart ideas??:)
by andreychek (Parson) on May 30, 2002 at 15:32 UTC
    You may also be able to use TheDamian's Quantum::Superpositions to do the trick for you. Perhaps something like the following code:
    #!/usr/bin/perl -w use strict; use Quantum::Superpositions; my @array1 = qw( 0 2 4 6 8 10 12 14 16 18 20 ); my @array2 = qw( 0 5 10 15 20 ); if(any(@array1) eq any(@array2)) { print "A match!\n"; } else { print "Nope, no match\n"; }
    As expected, the above example does find a match.

    -Eric

    --
    Lucy: "What happens if you practice the piano for 20 years and then end up not being rich and famous?"
    Schroeder: "The joy is in the playing."
Re: any smart ideas??:)
by Bilbo (Pilgrim) on May 30, 2002 at 14:58 UTC
    You could create a hash, with the elements of one array as the keys. The values contained in the hash aren't important. You can then loop over the other array checking whether each each element matches one of the keys of the hash.
    #!/usr/bin/perl -w use strict; # Set up the arrays my @array1 = qw(a b c d); my @array2 = qw(b a e f); # Create the hash, based on array1 my %hash; foreach (@array1) {$hash{$_} = 1;} # Loop through array2 looking for matches foreach (@array2) { if ($hash{$_}) {print $_, "\n"} }
Re: any smart ideas??:)
by dsheroh (Monsignor) on May 30, 2002 at 15:00 UTC
    If you just want the intersection of the two arrays and all values are unique within each array, something like this should work:
    #!/usr/bin/perl -w use strict; my @array1 = qw[a b c d e]; my @array2 = qw[a n o t h e r]; my %count; foreach my $element (@array1, @array2) { $count{$element} += 1; } foreach my $key (keys %count) { print "$key appears in both arrays\n" if $count{$key} == 2; }
    Output:
    $ ./foo.pl a appears in both arrays e appears in both arrays
    For something a little more complex (but also more robust, more flexible, and probably faster) you could do this:
    #!/usr/bin/perl -w use strict; my @array1 = qw[a b c d e]; my @array2 = qw[t e s t d a t a]; my @sort1 = sort @array1; my @sort2 = sort @array2; while (@sort1 && @sort2) { if ($sort1[0] eq $sort2[0]) { my $match = $sort1[0]; while (@sort1 && $sort1[0] eq $match) { shift @sort1; } while (@sort2 && $sort2[0] eq $match) { shift @sort2; } print "$match is in both arrays\n"; } elsif ($sort1[0] lt $sort2[0]) { shift @sort1; } else { shift @sort2; } }
    which produces
    $ ./bar.pl a is in both arrays d is in both arrays e is in both arrays
    without getting a false positive on 't' like the first version would.
Re: any smart ideas??:)
by marvell (Pilgrim) on May 30, 2002 at 15:14 UTC
    This can be found in the node mentioned above, the Perl Cookbook and a few other places.

    @array1 = (1,2,3,4,5); @array2 = (2,4,6,8,10); %map2 = map {$_ => 1} @array2; @intersection = grep ($map2{$_}, @array1); print "@intersection\n";

    --
    Steve Marvell

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2024-04-25 17:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found