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

Morning guys!

I have two arrays and I need to check whether all first array entries are contained in the second array.
Anyone has a short way to do that without having to loop on a loop here?

Thanks

Hotshot

Replies are listed 'Best First'.
Re: Array lookup
by Abigail-II (Bishop) on Apr 13, 2003 at 10:19 UTC
    my %hash; @hash {@first_array} = (); delete @hash {@second_array}; print "first array contains elements not in second array" if %hash;

    Abigail

Re: Array lookup
by Enlil (Parson) on Apr 13, 2003 at 09:45 UTC
    if we assume that all the first array entries are unique, then we can do this easily with a hash:
    use strict; use warnings; #USING A HASH TO CHECK IF ALL OF ARRAY2 IS IN ARRAY1 my @array1 = (1,2,3,4,5); my @array2 = (1,3,4,5); my %hash; @hash{@array1} = (); foreach (@array2) { unless ( exists $hash{$_} ) { die "Array1 does not contain $_\n" } } print "Yup they are all there\n";

    update: (striked out an irrelevent point)Another way to do it is with Quantum::Superpositions :

    update2 I realize I have it backwords and am checking that all of @array2 is in @array1, but if you switch the two (type @array1 where I had @array2, and vice versa) in the code above (and below), you will have what you want. Also, I really like Abigail-II's solution below. Anyhow here is one more way to do it with Quantum::Superpositions:

    -enlil

Re: Array lookup
by CountZero (Bishop) on Apr 13, 2003 at 15:34 UTC

    TIMTOWTDI

    • Sort both arrays
    • take the first element from array1 and starting at the top of array2 move down until either you find the same element in array2 (in which case you continue with the next element of array1) or reach an element which is larger than the element your were checking against (in which case you have found an element in array 1 which is not in array 2)

    The maximum number of comparisons would be the length of array1 + array2. Of course you have the overhead of the sorting to take into account, put perhaps you are lucky and they are sorted to start with (such as when they are the result of a database select).

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Array lookup
by Limbic~Region (Chancellor) on Apr 13, 2003 at 19:14 UTC
    hotshot,
    Please do not take this post too seriously

    I was trying to think outside the box and in the spirit of TIMTOWTDI

    #!/usr/bin/perl -w use strict; my @FirstArray = qw(one two three); my @SecondArray = qw(four seven one eight two nine three seventeen); unless (index ((join "" , sort map {"@FirstArray" =~ /\b($_)\b/;} @Sec +ondArray) , (join "" , sort @FirstArray)) eq -1) { print "Second array contains all the elements in first array\n"; + } else { print "Second array does not contain all the elements in the first + array\n"; }

    This is probably easily broken, but I thought it was neat.

    Cheers - L~R

      It will indeed break if you have duplicate elements in one or each (but not both) of the arrays.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

        CountZero,
        I am not sure I follow. The node said all elements (to include duplicates). If add a duplicate in @FirstArray, then there has to be a duplicate in @SecondArray to be valid (which works). If I add an duplicate element in the second array, the substring will just shift. Can you give me an example of a data set where it will not work? I am not saying there isn't one (I am fairly certain there is), but your logic doesn't match what my tests have shown.

        Cheers - L~R

        Update: As I was going to bed last night, I figured out when this wouldn't work. If the second array has duplicates that are in the middle of the list (not on either edge).

        I was thinking about an element being duplicated a number of times in one of the arrays but not in the other array but I now see that this will depend on how you define "all" in the original question. I understood it as "all duplicates are alike", but if you understand it as "all duplicates are different" then your program works (but all hash-based solutions are broken unless they keep an explicit tally of the number of each individual element).

        My solution suffers from the same "defect" as yours depending on whether or not you increment the index of the second array after you have found a match. If you don't increment the index, then duplicates are not relevant.

        Update: Fixed some typos.

        Thanks L~R for this insight.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      It will also not distinguish between 'fortynine' and 'forty' 'nine' if there are no other elements which fall alphabetically between 'forty' and 'nine' (granted, perhaps a somewhat rare condition).

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Array lookup
by vek (Prior) on Apr 14, 2003 at 03:47 UTC

      vek ++ for not re-inventing the wheel.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law