use Algorithm::Diff 'sdiff';
use Data::Dumper;
my @b = (2, 3, 4, 5);
my @c = sdiff(\@a, \@b);
print Dumper(\@c);
Output:
$VAR1 = [
[ '-', 1, '' ],
[ 'u', 2, 2 ],
[ 'u', 3, 3 ],
[ 'u', 4, 4 ],
[ '+', '', 5 ]
];
You can see that 1 has a '-' indicating it has been removed, and 5 has a '+' indicating it has been added. The other items have a 'u', indicating they are unchanged.
(source)
However, if comparing (a b c) with (c b a), Algorithm::Diff::sdiff will fail to realise that nothing has been added or removed. A simpler algorithm might be:
sub determine_changes {
my ($old, $new) = @_;
# Compare two lists
my %old_lookup = map { $_ => 1 } @$old;
my %new_lookup = map { $_ => 1 } @$new;
my @added = grep { ! $old_lookup{$_} } @$new;
my @removed = grep { ! $new_lookup{$_} } @$old;
my @changes;
push @changes, map { { item => $_, operation => 'add' } } @added;
push @changes, map { { item => $_, operation => 'remove' } } @removed;
my @sorted_changes = sort { $a->{item} cmp $b->{item} } @changes;
return \@sorted_changes;
}