Perl中不区分大小写的唯一数组元素
我使用模块List::MoreUtils导出的uniq函数来查找数组中的uniq元素。但是,我希望它以不区分大小写的方式查找uniq元素。我该怎么做 我已使用Data::Dumper转储了阵列的输出:Perl中不区分大小写的唯一数组元素,perl,uniq,Perl,Uniq,我使用模块List::MoreUtils导出的uniq函数来查找数组中的uniq元素。但是,我希望它以不区分大小写的方式查找uniq元素。我该怎么做 我已使用Data::Dumper转储了阵列的输出: #! /usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); use List::MoreUtils qw(uniq); use feature "say"; my @elements=<array is
#! /usr/bin/perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
use List::MoreUtils qw(uniq);
use feature "say";
my @elements=<array is formed here>;
my @words=uniq @elements;
say Dumper \@words;
预期输出应为:john,john
只有2个元素,其余的都应该被过滤,因为它们是同一个单词,只是大小写不同
如何删除忽略大小写的重复元素?使用小写字母,并附带一条语句:
my @uniq_no_case = uniq map lc, @elements;
uniq区分大小写的原因是它依赖于散列的重复数据消除特性,这也是区分大小写的。uniq的代码如下所示:
sub uniq {
my %seen = ();
grep { not $seen{$_}++ } @_;
}
如果您想在自己的代码中直接使用此sub,可以将lc
合并到其中:
sub uniq_no_case {
my %seen = ();
grep { not $seen{$_}++ } map lc, @_;
}
解释其工作原理:
@
包含到子例程的参数,它们被馈送到grep
语句。当通过代码块时返回true的任何元素都由grep语句返回。代码块由几个更精细的点组成:
第一次看到元素时返回0。该值仍然递增为1,但在返回后(与$seen{$\}++
谁先inc,然后返回相反)+$seen{$\u}
- 通过对递增的结果求反,我们得到第一个键为true,后续每个键为false。因此,该列表将被删除
作为sub中的最后一条语句将返回一个列表,该列表由sub返回grep
仅将map lc,@
函数应用于lc
中的所有元素@
my %seen;
my @unique;
for my $w (@words) {
next if $seen{lc($w)}++;
push(@unique, $w);
}
# @unique has the unique words
请注意,这将保留原始单词的大小写
更新:正如评论中所指出的,OP需要什么并不清楚,但我这样写解决方案是为了说明一种通用技术,即从某个“等价关系”下的列表中选择唯一的代表在这种情况下,等价关系是word$a
等价于word$b
当且仅当lc($a)eq lc($b)
大多数等价关系可以用这种方式表示,也就是说,该关系由分类器函数f()
定义,使得$a
等价于$b
当且仅当f($a)eq f($b)
。例如,如果我们想说两个单词的长度相同,那么f()
就是length()
现在您可能明白了我为什么这样编写算法了——分类器函数可能不会生成原始列表中的值。在
f=length
的情况下,我们希望选择单词,但是单词的f
是一个数字。这与List::MoreUtils模块导出的uniq函数相同?确实如此。虽然由于子模块非常简单和简短,但您可以复制粘贴它,并保存加载模块的过程。谢谢。我会理解子程序,然后直接使用:)你能解释一下grep语法吗?哈希%seen使用数组的元素作为键,并检查它们是否出现。“但是,我不确定整个语法是如何工作的。”NeonFlash在我的回答中补充了一个解释。我认为这是一个写得相当巧妙的sub。@NeonFlash如果这个答案能让您满意地解决问题,请不要忘记通过单击复选标记来接受它。在哈希访问中使用lc
比给出的其他解决方案好得多,因为它保留了(第一个匹配)输入的案例。@LeoNerd你到底在说什么?在哈希之前和内部使用lc没有区别。我的意思是,与映射lc不同。。。另一个答案给出了解决方案。这个更好,因为它返回的值是原来的大小写,而不是强制小写。啊哈,我现在明白了。然而,这不是OP所要求的。此外,谁能说原来的情况是可取的呢?通常,名称是ucfirst(lc)。我确信uniq()库比这个版本有更多的支持和效率。
my %seen;
my @unique;
for my $w (@words) {
next if $seen{lc($w)}++;
push(@unique, $w);
}
# @unique has the unique words