Intersection and union of array by hash

Hi,

A piece of script from Perl-cookbook I do not understand, and post here for explanation.
The purpose is to find the element in either array (union), and in both array (intersection). Thank you in advance.

@a=qw(1 3 5 6 7 8);
@b=qw(2 3 5 7 9);

foreach $e (@a, @b) {$union{$e}++ && $isect{$e}++}

@union = keys %union;
@isect = keys %isect;

How is the third line:

foreach $e (@a, @b) {$union{$e}++ && $isect{$e}++}

working behind? I am desperate to understand it.

We loop through the elements of these two arrays:

@a=qw(1 3 5 6 7 8);
@b=qw(2 3 5 7 9);

The first time a value is seen, its value in the hash union is 0, so it evaluates to false. The second part of the expression $union{$e}++ && $isect{$e}++ , the post-increment assignment of the hash isect is not evaluated:

In the first iteration we have:

  1. $e gets the value of 1.
  2. $union{ $e }++ evaluates to false, $union{ $e } becomes 1 after the expression is evaluated (because it's post-incremented, ++$union{ $e } is the opposite, it will first assign the value of 1 to the variable and after that, the expression will get evaluated, using the new value).
  3. $isect{ $e }++ is skipped, because the first part of the expression is false.

Second iteration:

  1. $e gets the value of 3 (the second element in the first array).
    2 to 3 are the same as in the first case.

...

This way, we build the union of the two sets.

8th iteration:

  1. $e gets the value of 3 (the second element in the second array).
  2. $union{ $e }++ this time evaluates to true, it's current value is 1, the next one will be 2.
  3. $isect{ $e }++ gets evaluated this time, because the first evaluates to true.
    So this hash will contain only the values previously seen (those present in the first array (assuming each array contains only unique values).

So now we are able to build the intersection of those two sets.

HTH

1 Like

Thanks!
I got it now, but it seems to me if there is duplicate items in either of the arrays, it won't work, right?

Thank you again!

YT

Correct. That's why I said "assuming each array contains only unique values".

The union will work anyway (it's a union, not union all).

1 Like