Удаление дубликатов обычно выполняется следующим образом:
use List::Util 1.44 qw( uniqnum );
@a = uniqnum @a;
или
my %seen;
@a = grep { !$seen{$_}++ } @a;
Чтобы достичь того, что вы хотите, нам просто нужна цепочка grep
, которая удаляет другие нежелательные элементы.
use List::Util 1.44 qw( uniqnum );
@a = uniqnum grep { $counts{$_} % 2 } @a;
или
my %seen;
@a = grep { !$seen{$_}++ } grep { $counts{$_} % 2 } @a;
или
my %seen;
@a = grep { ( $counts{$_} % 2 ) && !$seen{$_}++ } @a;
Приведенные выше решения основаны на подсчете каждого значения. Чтобы получить это, мы можем использовать следующее:
my %counts;
++$counts{$_} for @a;
Все вместе:
my ( %counts, %seen );
++$counts{$_} for @a;
@a = grep { ( $counts{$_} % 2 ) && !$seen{$_}++ } @a;
Обратите внимание, что эти методы удаления дубликатов сохраняют порядок элементов (сохраняя первый дубликат). Это более эффективно (O (N)), чем использование sort
(O (N log N)), чтобы избежать создания чего-то недетерминированного.