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

HI all I am very new to perl... I was just wondering about the solution to this question. I have two arrays A and B containing integers. Now i want to merge the two arrays. I was kinda confused with the syntax in perl so I didnt know which method to chhose. Anyways the idea is to remove the elements in B that exist in A before merging them. An efficient algorithm would be helpful Thanks Regards Perl_Krishna

20040818 Edit by ysth: change title from Simple question I guess

Replies are listed 'Best First'.
Re: Merging Arrays without duplicates
by ccn (Vicar) on Aug 18, 2004 at 13:35 UTC

    simple merge @merge = (@A, @B)

    for more tricks see perlfaq4 {Data Arrays}

    upd: To merge without duplicates:

    @A = (1,2,3,4,5,6); @B = (1,2,3,4,5,6,7,8,9); @seen{@A} = (); @merged = (@A, grep{!exists $seen{$_}} @B); print @merged;
      yup jus got there (to faq4 i mean) ...... guess now i got to become a perl junkie :D
      hey i am new to this ... could u explain real quick wat lines 3 and 4 do? Thanks Krish

        @seen{@A} = ();
        is the same as

        $seen{$A[0]}) = undef; $seen{$A[1]}) = undef; $seen{$A[2]}) = undef; $seen{$A[3]}) = undef; ...

        @merged = (@A, grep{!exists $seen{$_}} @B);
        is the same as

        @C = grep{!exists $seen{$_}} @B; @merged = (@A, @C);

        @C = grep{!exists $seen{$_}} @B;
        @C is assigned the contents of @B not seen in %seen. In other words,
        @C is assigned the contents of @B not seen in @A.

Re: Merging Arrays without duplicates
by gellyfish (Monsignor) on Aug 18, 2004 at 13:37 UTC

    If you want to perform a merge which removes the duplicates then you might want some thing like:

    my %seen; my @out = grep( !$seen{$_}++, @A, @B)
    There are other examples in the perlfaq4

    /J\

Re: Merging Arrays without duplicates
by rsteinke (Scribe) on Aug 18, 2004 at 13:40 UTC

    To remove duplicate elements, use an intermediate hash:

    my @out = keys %{{map {($_ => 1)} (@A, @B)}};
    The double %{{}} on the outside are necessary, as the inner pair creates a hash reference, and the outer %{} dereferences it.

    Ron Steinke
    <rsteinke@w-link.net>
Re: Merging Arrays without duplicates
by gaal (Parson) on Aug 18, 2004 at 13:40 UTC
    Do you need to maintain the original order? Is the result supposed to be sorted?

    If the answer to the first question is "no" or if the answer to the second one is "yes", this will work:

    my @merged = sort { $a <=> $b } keys %{ { map { $_ => 1 } } } @A, @B;

    If order isn't an issue simply remove the sort { $a <=> $b } bit.

Re: Merging Arrays without duplicates
by Mr_Person (Hermit) on Aug 18, 2004 at 15:25 UTC
    And just for fun, here's another way to do it using Tie::Array::Unique.
    use Tie::Array::Unique; my @a = (0,1,2,3,4,5,6,7); my @b = (3,4,5,6,7,8,9,10); tie my(@merged), 'Tie::Array::Unique', (@a,@b); print join(',', @merged);
    Will output 0,1,2,3,4,5,6,7,8,9,10.
Re: Merging Arrays without duplicates
by bgreenlee (Friar) on Aug 18, 2004 at 13:45 UTC

    Sounds suspicously like a homework problem...but anyway, if you don't care about order, just dump them all into a hash. If you do care about order, there are some modules in CPAN that will do the trick: Tie::IxHash, Tie::Hash::Indexed, Tie::LLHash. If want to preserve order and cook it yourself, one way to do it is to make a hash with the data from one of the arrays (probably the larger), then iterate through the other array, pushing onto the first array any elements in the second array that aren't found in the hash.

    -b

Re: Merging Arrays without duplicates
by husker (Chaplain) on Aug 18, 2004 at 15:44 UTC
    If this isn't homework, then using Set::Array might save you a lot of time.