in reply to Comparing Two Arrays

Yet another (non-iterative) variation on the same (hash) theme:
my @union = do { my %hash; @hash{@array1,@array2}=(); keys %hash };

Replies are listed 'Best First'.
Re: Re: Arrays
by rje (Deacon) on Dec 08, 2001 at 00:59 UTC
    Hey, that's very cool! This is starting to look like
    a golf match. Let me use your method to remove the
    foreach() loop from my solution:
    my %hash = (); @hash{ @array1, @array2 } = (); @array3 = keys %hash;

    I say once again: This is very cool!

    Rob

      ... or even:
      @array3 = keys %{{ map {$_ =>1} @array1, @array2 }};
      - danboo
        Oooooh!

        The force is strong in that one.

        Rob

        @array3 = keys %{{ map {$_ =>1} @array1, @array2 }};

        I see no need for a map here:

        my @union = keys %{{(@array1,@array2)x2}};
      Let me explain this (I've noticed that non-iterative
      solutions are often odd-looking because they have no
      cognate in the non-perl world):
      my %hash = ();
      This just creates a new, empty, associative array.
      @hash{ @array1, @array2 } = ();
      In this single line, the associative array has effectively
      removed the duplicates from @array1 and @array2 for free.

      This is a list assignment; that is, this single line
      assigns into multiple keys. Just as $hash{$foo} = 0
      creates a string key from $foo in the hash %hash,
      so @hash{ @array } creates a bunch of keys, whose
      members are named in @array, in the hash %hash. Also,
      since two arrays mashed together form one big array--
      that is, (@a1,@a2,@a3) becomes one flat array-- so then
      the assignment @hash{ @array1, @array2 } creates string
      keys out of each element in the arrays for %hash.
      Since we know that keys are by nature unique, the
      hashtable has removed the duplicates for us, for free!
      So, now all there is left to do is extract the keys
      from the hashtable:

      @array3 = keys %hash;

      ...and we're done.

      Rob

      Let's establish some ground rules.

      Provide a function that takes two arrayrefs, combines them and returns an array containing all the elements in the previous two arrays, bu no duplicates.

      As I don't know them, you can't use commandline opts. *grins*

      my @arr1 = (1, 2, 3, 4, 5); my @arr2 = (4, 5, 6, 7, 8); my @arr3 = f(\@arr1, \@arr2); sub f { #234567890#234567890#234567890 @h{map{@$_}@_}=1;keys%h }
      23 characters, and I know I can do better.

      Update: 22 chars

      @h{map@$_,@_}=1;keys%h

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        20 chars:
        sub union { keys%{{map{$_,1}@_}} }
        - danboo

        EDIT: oops, didn't pay attention to instructions. scratch that.