Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Array compare not matching all elements

by Dnamonk3 (Novice)
on Oct 29, 2018 at 14:04 UTC ( [id://1224845]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks, I am trying to compare value of 2 arrays and it's not returning all the matching values between 2 arrays: Below is my code:
#!/bin/perl @array1 = ("A2","A5","C1","G0","T3","T4"); @array2 = ("A2","A3","A5","G1","G0","G4"); #@array1 = sort { $a <=> $b } @a1; #@array2 = sort { $a <=> $b } @a2; for($i = 0; $i <= $#array1; $i++){ while ($array1[$i] eq $array2[$i]){ print $array1[$i]."\n"; last; } }
Sorting isn't helping either. For example in above arrays matching elements are: A2, A5 and G0.

But my code is only printing A5 ! I tried using forloop etc but doesn't work !

Thanks in advance for help.

Best

Replies are listed 'Best First'.
Re: Array compare not matching all elements
by 1nickt (Canon) on Oct 29, 2018 at 14:10 UTC

    Hi, the classic technique is to put the elements of one array into a hash and see if the elements of the other array have keys in the hash.

    Update: Here's an example, with some points to consider:

    • Always use strict and warnings. Whoever showed you Perl for the first time should be beaten for not telling you that.
    • Declare your variables with my to keep them under control.
    • Use map to quickly loop through an list if you want to use the loop to make another list.
    • A hash is a type of array, so can be built with map by alternating keys and values.
    • When you use for or foreach, Perl will handle exiting the loop when the list is empty.
    • You can use if in the traditional way with braces, or as a postfix condition.
    • use strict; use warnings; use feature 'say'; my @array1 = ("A2","A5","C1","G0","T3","T4"); my @array2 = ("A2","A3","A5","G1","G0","G4"); my %lookup = map { $_ => 1 } @array1; for my $thing ( @array2 ) { say "I found $thing" if $lookup{ $thing }; } __END__

      Hope this helps!


      The way forward always starts with a minimal test.
      Awesome! Thank you :)
Re: Array compare not matching all elements
by hippo (Bishop) on Oct 29, 2018 at 14:11 UTC
      Thanks !
Re: Array compare not matching all elements
by roboticus (Chancellor) on Oct 29, 2018 at 14:50 UTC

    Dnamonk3:

    Typically you use hashes when you want to compare the contents of arrays to find all matches. You might find something like this more useful:

    my %temp_for_compare; # Add values from the first array into the temporary hash $temp_for_compare{$_} = 0 for @array1; # Now we can simply check the items in the second array against the ha +sh for my $val (@array2) { if (exists $temp_for_compare{$val}) { print "$val in both arrays\n"; } }

    As you can see, it's fairly straightforward.

    You can do it with arrays, but you either get something slow or something a little more complex. The slow version is to simply compare each item in the array with each item in the other array. Don't do it this way!:

    for my $a1val (@array1) { for my $a2val (@array2) { if ($a1val eq $a2val) { print "$a1val in both arrays\n"; } } }

    The problem with doing it this way is that while it's simple, it gets slow pretty quickly. If you have 100 items in each array, then you run through the loop 100*100 times.

    With a little more code, you can make it better by sorting the arrays and checking them pairwise. First, you'll have to sort your arrays. Since it's a destructive procedure, you'll want to make copies of your arrays if you want to keep them around after the comparison. Then you simply check the first value of each array: If they match, you found a pair of values in both arrays. Otherwise, you discard the smaller of the two values and check again. You stop when one of the arrays is empty:

    my @tmpArray1 = sort @array1; my @tmpArray2 = sort @array2; # You run out of matches when either array is empty while (@tmpArray1 and @tmpArray2) { if ($tmpArray1[0] eq $tmpArray2[0]) { print "$tmpArray1[0] in both arrays\n"; shift @tmpArray1; shift @tmpArray2; } elsif ($tmpArray1[0] lt $tmpArray2[0]) { # tmpArray1 has an item not in tmpArray2, so get rid of # it and try the next element shift @tmpArray1; } else { # tmpArray2 has an item not in tmpArray1, so get rid of # it and try next element shift @tmpArray2; } }

    If you have 100 items in each array, you run through the loop at most 200 times. (Of course, you have the added time penalty of the sort operation.)

    If you compare it to the hash operation, then you have a loop of 100 operations to build the hash, and then 100 operations to check the other array against the hash.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Array compare not matching all elements
by BillKSmith (Monsignor) on Oct 29, 2018 at 15:31 UTC
    It is often worth the effort to look for a module even to do simple tasks. In this case consider the function 'intersect' in the module Array::Utils. An added benefit is that although your spec 'compare value of 2 arrays' is ambiguous, the word 'intersect' is not. It says exactly what you mean.
    $type Dnamonk3.pl use strict; use warnings; use Array::Utils qw(intersect); my @array1 = ("A2","A5","C1","G0","T3","T4"); my @array2 = ("A2","A3","A5","G1","G0","G4"); { local $, = ','; print intersect(@array1, @array2); } $perl Dnamonk3.pl A2,A5,G0
    Bill
Re: Array compare not matching all elements
by dorko (Prior) on Oct 29, 2018 at 17:58 UTC
    My favorite solution for this type of problem is List::Compare.

    Cheers,

    Brent

    -- Yeah, I'm a Delt.
Re: Array compare not matching all elements
by cavac (Parson) on Oct 29, 2018 at 16:06 UTC

    You already got some great solutions. Here's my 2 cents:

    #!/usr/bin/env perl use strict; use warnings; use diagnostics; use Array::Contains; my @array1 = ("A2","A5","C1","G0","T3","T4"); my @array2 = ("A2","A3","A5","G1","G0","G4"); foreach my $elem (@array1) { print "$elem\n" if(contains($elem, \@array2)); }

    Edit: I just love those kind of Perl questions where there are so many different solutions to choose from. Really shows of the flexibility of the language!

    perl -e 'use MIME::Base64; print decode_base64("4pmsIE5ldmVyIGdvbm5hIGdpdmUgeW91IHVwCiAgTmV2ZXIgZ29ubmEgbGV0IHlvdSBkb3duLi4uIOKZqwo=");'

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (2)
As of 2024-04-25 01:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found