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

I had written a code that was working fine until today. Part of the code finds elements in one array that are not present in another array. I have two arrays
1. @sorted_original_cellnames 2. @sorted_top_cellnames
To find the elements that are not found in the first array I wrote
@test1{@sorted_original_cellnames} = undef; @not_found_in_original = grep{!exists $test1{$_}}@sorted_top +_cellnames;
Similarly for the second array I wrote
@test2{@sorted_top_cellnames} = undef; @not_found_in_topcell = grep{!exists $test2{$_}}@sorted_orig +inal_cellnames;
This code was working fine as long as we had the same number of elements in both the arrays. Today I have a new situation -> I have 71 items in the first array and only 66 items in the second. The code is not working properly. It generates  @not_found_in_originalarray with 5 elements of nothing and the @not_found_in_topcell with 5 elements that are missing. Also the code gives following errors
Use of uninitialized value in exists at checkmodlist.pl line 355. Use of uninitialized value in hash slice at checkmodlist.pl line 358.
I tried rewriting the code with foreach, still I get the same problem, any idea to correct this. Thanks in adavance for all who helps me. Augustine

Replies are listed 'Best First'.
Re: Extracting elements in one array but not in another
by neilh (Pilgrim) on Oct 23, 2004 at 03:49 UTC
    From perlman:perlfaq4:

    How do I compute the intersection of two arrays?

    Use a hash. Here's code to do both and more. It assumes that each element is unique in a given array:

    @union = @intersection = @difference = (); %count = (); foreach $element (@array1, @array2) { $count{$element}++ } foreach $element (keys %count) { push @union, $element; push @{ $count{$element} > 1 ? \@intersection : \@diff erence }, $element; }
Re: Extracting elements in one array but not in another
by Zaxo (Archbishop) on Oct 23, 2004 at 03:55 UTC

    I believe that one or both of your new arrays has undefined elements in it. Your hash lookup is the correct way to do this, and the relative sizes of the arrays don't matter. Try filtering out undefined elements from arrays if they are unavoidable from the data. @array = grep { defined } @array;

    After Compline,
    Zaxo

      I agree that either @sorted_original_cellnames or @sorted_top_cellnames must have undefined elements in it. I tried the following code:
      #! /usr/bin/perl -w use strict; my @a = (1,2,3,4,5); my @b = (2,4,6,8); my %c; @c{@a} = undef; my @bb = grep { ! exists $c{$_} } @b; my %d; @d{@b} = undef; my @aa = grep { ! exists $d{$_} } @a; print "@aa\n"; print "@bb\n";
      and I got the following output with no warnings:
      1 3 5 6 8
      If I add an undef to @a or @b in my example, I get the warnings you describe.
Re: Extracting elements in one array but not in another
by emazep (Priest) on Oct 23, 2004 at 06:50 UTC
    To find elements that are in one array but not in another, there is a nice loopless solution from the Perl Cookbook which uses the delete function:
    my %seen; @seen{ @original_1 } = (); delete @seen{ @original_2 }; my @original_1_only = keys %seen;
    Of course there is also a loopy solution, should you prefer it:
    my %seen; my @original_1_only; @seen{ @original_2 } = (); foreach (@original_1) { push(@original_1_only, $_) unless exists $seen{$_}; };
    Stick with these.

    Ciao,
    Emanuele.
Re: Extracting elements in one array but not in another
by DrHyde (Prior) on Oct 25, 2004 at 09:12 UTC
Re: Extracting elements in one array but not in another
by TomDLux (Vicar) on Oct 25, 2004 at 14:23 UTC

    The solutions above are correct but tedious, in that you have to code the solution yourself.

    If you prefer a lazy solution, let Jim Keenan do the hard part, and just install his module, List::Compare

    --
    TTTATCGGTCGTTATATAGATGTTTGCA