我有一个数组
[ 1, 0, 0, 0, 5, 2, 4, 5, 2, 2 ]
我需要删除大量的重复项。
这意味着,如果一个值在数组中出现偶数次,则将它们全部删除,但如果它出现奇数次,则只保留一个。
上面数组的结果应为
[ 1, 0, 2, 4 ]
我该怎么做?
答案 0 :(得分:5)
删除重复项通常按如下方式完成:
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))以避免产生非确定性的东西。
答案 1 :(得分:3)
这真的不难,而且自己完全没有尝试解决它是非常糟糕的形式。我希望有人发布这样的问题来描述让别人为他们工作的感觉。即使是困难的填字游戏也不会获得大量的解决方案请求,但在这种情况下,您可能会因其他人编写的解决方案而获得报酬?为什么这不是问题?
构建哈希以计算每个值的当前计数
使用$_ % 2
确定新的最终计数
将哈希解构为新数组
my $array = [ 1, 0, 0, 0, 5, 2, 4, 5, 2, 2 ];
my @new_array = do {
my %counts;
++$counts{$_} for @$array;
map {
( $_ ) x ( $counts{$_} % 2 )
} sort { $a <=> $b } keys %counts;
};
use Data::Dump;
dd \@new_array;
[0, 1, 2, 4]
答案 2 :(得分:1)
请参阅评论,了解这种可能的解决方案是如何做到的。
#!/usr/bin/perl
use strict;
use warnings;
my @a = qw(1 0 0 0 5 2 4 5 2 2);
# Move through the array.
for (my $i = 0; $i < scalar(@a); ) {
# Move through the positions at and ahead of current position $i
# and collect all positions $j, that share the value at the
# current position $i.
my @indexes;
for (my $j = $i; $j < scalar(@a); $j++) {
if ($a[$j] == $a[$i]) {
push(@indexes, $j);
}
}
if (scalar(@indexes) % 2) {
# If the number of positions collected is odd remove the first
# position from the collection. The number of positions in the
# collection is then even afterwards.
shift(@indexes);
# As we will keep the value at the current position $i no new
# value will move into that position. Hence we have to advance
# the current position.
$i++;
}
# Move through the collected positions.
for (my $k = 0; $k < scalar(@indexes); $k++) {
# Remove the element at the position as indicated by the
# $k'th element of the collect positions.
# We have to subtract $k from the collected position, to
# compensate for the movement of the remaining elements to the
# left.
splice(@a, $indexes[$k] - $k, 1);
}
}
print("@a");
答案 3 :(得分:0)
你有很多答案,这是另一个答案:
use strict;
use warnings;
use Data::Dumper;
my $input = [ 1, 0, 0, 0, 5, 2, 4, 5, 2, 2 ];
my $output = dedupe_evens($input);
print Data::Dumper->Dump([$input, $output], ['$input', '$output']);
exit;
sub dedupe_evens {
my($input) = @_;
my %seen;
$seen{$_}++ foreach @$input;
my @output = grep {
my $count = delete $seen{$_}; # only want first occurrence
$count && $count % 2;
} @$input;
return \@output;
}
产生此输出(为简洁而重新格式化):
$input = [ 1, 0, 0, 0, 5, 2, 4, 5, 2, 2 ];
$output = [ 1, 0, 2, 4 ];