=pod extract_key takes an element from a list and returns a scalar that is the key element. Think of MD5. =cut sub extract_key { # blindly return the item itself, stringified. return "@_"; }; sub compare_items { # plain string identity comparision $_[0] eq $_[1] }; sub compare_lists { my ($list_a, $list_b) = @_; my (%dict); my %result = ( equal => [], different => [], only_a => [], only_b => [], ); for my $item_a (@$list_a) { my $key = extract_key($item_a); $dict{$key} = [] unless exists $dict{$key}; push @$dict{$key}, $item_a; }; my @found; for my $item_b (@$list_b) { my $key = extract_key($item_b); if (exists $dict{$key}) { if (@$dict{$key}) { my $item_a = shift @$dict{$key}; push @found, [ $item_a, $item_b ]; } else { push $result{only_b}, $item_b; }; }; }; push $result{only_a}, @$dict{$key} for my $key (keys %dict); for my $pair (@found) { if (compare_items( $pair->[0], $pair->[1] )) { push @$result{equal}, $pair; } else { push @$result{different}, $pair; }; }; return %result; };