sub set_comm # named after the unix utility "comm" { my @ar = @_; # two sets, passed as array(ref)s. # make the corresponding sets: my @hr = map { my %h; @h{@$_} = (); \%h } @ar; # figure out which is shorter, since we'll be iterating # over that list of keys: my( $shorter, $longer ) = keys %{$h[0]} < keys %{$h[1]} ? ( 0, 1 ) : ( 1, 0 ); # determine common keys: my @common = grep { exists $hr[$longer]{$_} } keys %{$hr[$shorter]}; # remove those from the sets: delete @{$hr[0]}{@common}; delete @{$hr[1]}{@common}; # return "in first only, in second only, in both": return( [ keys %{$hr[0]} ], [ keys %{$hr[1]} ], \@common ); }