Answers:
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
输出:
one two three
如果你想使用一个模块,尝试uniq
从功能List::MoreUtils
my
在这个范围内这是一个词汇,所以很好。话虽如此,可能会选择一个更具描述性的变量名。
$::a
and $::b
,不是吗?
sub uniq { my %seen; grep !$seen{$_}++, @_ }
这是一个更好的实现,因为它可以免费保留订单。甚至更好的是,使用List :: MoreUtils中的一个。
Perl文档附带了很多常见问题解答。您的问题经常被问到:
% perldoc -q duplicate
从上面命令的输出中回答,复制和粘贴如下所示:
在/usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod中找到 如何从列表或数组中删除重复的元素? (由brian d foy贡献) 使用哈希。当您认为“独特”或“重复”一词时,请考虑 “哈希键”。 如果您不在乎元素的顺序,则可以 创建哈希,然后提取密钥。你怎么不重要 创建该哈希值:仅使用“键”来获取唯一元素。 我的%hash = map {$ _,1} @array; #或哈希切片:@hash {@array} =(); #或foreach:$ hash {$ _} = 1 foreach(@array); 我的@unique =键%hash; 如果要使用模块,请尝试使用“ uniq”功能 “列表:: MoreUtils”。在列表上下文中,它返回唯一元素, 将其顺序保留在列表中。在标量上下文中,它返回 独特元素的数量。 使用List :: MoreUtils qw(uniq); 我的@unique = uniq(1、2、3、4、4、5、6、5、7); #1,2,3,4,5,6,7 我的$ unique = uniq(1、2、3、4、4、5、6、5、7); #7 您还可以浏览每个元素,并跳过已看到的元素 之前。使用哈希来跟踪。循环第一次看到 元素,该元素在%Seen中没有键。“下一个”语句创建 键并立即使用其值,即“ undef”,因此循环 继续到“推”并增加该键的值。下一个 当循环看到相同的元素时,其键存在于哈希中 该键的值是true(因为它不是0或“ undef”),所以 next跳过该迭代,循环转到下一个元素。 我的@unique =(); 我的%seen =(); foreach我的$ elem(@array) { 接下来,如果$ seen {$ elem} ++; 推@unique,$ elem; } 您可以使用grep进行更简短的编写,其功能相同 事情。 我的%seen =(); 我的@unique = grep {!$ seen {$ _} ++} @array;
然后在您的代码中:
use strict;
use warnings;
use List::MoreUtils qw(uniq);
my @dup_list = qw(1 1 1 2 3 4 4);
my @uniq_list = uniq(@dup_list);
@dup_list
应该在uniq
通话中,而不是@dups
逻辑:哈希只能具有唯一键,因此要遍历数组,为数组的每个元素分配任何值,并保留元素作为该哈希的键。返回哈希的键,它是您的唯一数组。
my @unique = keys {map {$_ => 1} @array};
如果我们应该在代码中多次使用此功能,则最好创建一个子例程。
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtils
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
先前的答案几乎总结了完成此任务的可能方式。
不过,我建议对于那些谁的修改不关心计数的重复,但这样做对井井有条。
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
请注意,先前建议的grep !$seen{$_}++ ...
加法$seen{$_}
在取反之前会增加,因此无论是否已经发生,都会发生该增加%seen
。但是,上述情况会在$record{$_}
true 时发生短路,一旦“关闭%record
”,就会听到听到的声音。
您还可以选择这种可笑性,它利用了自动生存和哈希键的存在:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
但是,这可能会导致一些混乱。
如果您不关心顺序或重复计数,则可以使用哈希片和我刚才提到的技巧进行另一次黑客入侵:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }
整洁。
试试看,似乎uniq函数需要一个排序列表才能正常工作。
use strict;
# Helper function to remove duplicates in a list.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @teststrings = ("one", "two", "three", "one");
my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";
使用唯一哈希键的概念:
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
输出:acbd