Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 什么';使用Perl检查数据数组中重复项的最有效方法是什么?_Arrays_Perl - Fatal编程技术网

Arrays 什么';使用Perl检查数据数组中重复项的最有效方法是什么?

Arrays 什么';使用Perl检查数据数组中重复项的最有效方法是什么?,arrays,perl,Arrays,Perl,我需要查看字符串数组中是否存在重复项,最节省时间的方法是什么?不是直接答案,但这将返回一个没有重复项的数组: #!/usr/bin/perl use strict; use warnings; my @arr = ('a','a','a','b','b','c'); my %count; my @arr_no_dups = grep { !$count{$_}++ } @arr; print @arr_no_dups, "\n"; 创建散列或集合,或使用 当您遇到每个字符串/输入时,请检

我需要查看字符串数组中是否存在重复项,最节省时间的方法是什么?

不是直接答案,但这将返回一个没有重复项的数组:

#!/usr/bin/perl

use strict;
use warnings;

my @arr = ('a','a','a','b','b','c');
my %count;
my @arr_no_dups = grep { !$count{$_}++ } @arr;

print @arr_no_dups, "\n";

创建散列或集合,或使用

当您遇到每个字符串/输入时,请检查散列中是否有该字符串/输入的实例。如果是这样,它就是一个复制品(你想怎么做就怎么做)。否则,使用字符串作为键向散列中添加一个值(例如,哦,比如,数字1)

示例(使用Python collections.Counter):

这些计数器是围绕字典(散列映射集合的Pythons名称)构建的

这是非常省时的,因为哈希键是索引的。在大多数情况下,键的查找和插入时间是在接近恒定的时间内完成的。(事实上,Perl“hash”之所以被称为“hash”,是因为它们是使用一种称为“hashing”的算法技巧实现的——这是一种校验和,当输入任意输入时,它的冲突概率极低)


如果将值初始化为整数(从1开始),则可以在哈希中找到每个值的键时对其进行递增。这几乎是计算字符串的最有效的通用方法。

我喜欢Perl的一个地方是它几乎可以像英语一样阅读。这有点道理

use strict;
use warnings;

my @array = qw/yes no maybe true false false perhaps no/;

my %seen;

foreach my $string (@array) {

    next unless $seen{$string}++;
    print "'$string' is duplicated.\n";
}
输出
“false”重复。

“no”重复。


将数组转换为哈希是最快的方法[
O(n)
],尽管它的内存效率很低。使用for循环比grep快一点,但我不知道为什么

#!/usr/bin/perl

use strict;
use warnings;

my %count;
my %dups;
for(@array) {
    $dups{$_}++ if $count{$_}++;
}
一种内存有效的方法是对数组进行适当排序,并遍历数组以查找相等和相邻的条目

# not exactly sort in place, but Perl does a decent job optimizing it
@array = sort @array;

my $last;
my %dups;
for my $entry (@array) {
    $dups{$entry}++ if defined $last and $entry eq $last;
    $last = $entry;
}
由于排序的原因,这是
nlogn
速度,但只需要在
%count
中存储重复的数据,而不是第二个数据副本。最坏情况下的内存使用率仍然是
O(n)
(当所有内容都被复制时),但是如果您的阵列很大,并且没有太多的重复项,那么您将获胜


撇开理论不谈,基准测试表明,后者在复制率较高的大型阵列(如超过100万个)上开始出现损失。

如果您仍然需要未经配置的阵列,则使用高度优化的库是最快的,然后将结果与原始结果进行比较:

use strict;
use warnings;
use List::MoreUtils 'uniq';

my @array = qw(1 1 2 3 fibonacci!);
my @array_uniq = uniq @array;
print ((scalar(@array) == scalar(@array_uniq)) ? "no dupes" : "dupes") . " found!\n";
或者,如果列表很大,并且您希望在找到重复条目后立即退出,请使用哈希:

my %uniq_elements;
foreach my $element (@array)
{
    die "dupe found!" if $uniq_elements{$element}++;
}

除非您有一些特定的要求,例如“我必须在不到一秒钟的时间内删除100000个整数的列表”,否则请不要询问做某事最省时的方法。否则,您会担心做某事无缘无故需要多长时间。

类似于@Schwern的第二个解决方案,但要在稍早一点的时候从
sort
的比较函数中检查重复项:

use strict;
use warnings;

@_ = sort { print "dup = $a$/" if $a eq $b; $a cmp $b } @ARGV;

它不会像散列解决方案那样快,但它需要更少的内存,而且非常可爱

感谢您的全面回答!我现在是用后一种方式做的,但内存不是问题,只是时间,所以我肯定要将它作为哈希重新实现。
my$duppes\u found=!!grep{$\ 1}值%countgrep
。实际上甚至
my$duppes\u found=@arr==@arr\u no\u duppes应该可以工作。也许OP只是好奇(尽管我同意,除非它被证明是一个瓶颈,否则不值得担心)。无论如何,这应该是对这个问题的评论,而不是回答。
use strict;
use warnings;

@_ = sort { print "dup = $a$/" if $a eq $b; $a cmp $b } @ARGV;