A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Determine differences in an array with Perl

Not just checking whether or not two arrays are the same, but finding out how they are different, i.e. what has been added and what has been taken away:

use Algorithm::Diff 'sdiff';
use Data::Dumper;

my @a = (1, 2, 3, 4);
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;
}