我使用模块导出的uniq函数,List :: MoreUtils来查找数组中的uniq元素。但是,我希望它以不区分大小写的方式查找uniq元素。我怎么能这样做?
我使用Data :: Dumper转储了Array的输出:
#! /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;
输出:
$VAR1 = [
'John',
'john',
'JohN',
'JOHN',
'JoHn',
'john john'
];
预期输出应该是:john,john john
只有2个元素,其余全部应该被过滤,因为它们是同一个单词,只有区别在于大小写。
如何删除忽略大小写的重复元素?
答案 0 :(得分:9)
my @uniq_no_case = uniq map lc, @elements;
List::MoreUtils'
uniq
区分大小写的原因是它依赖于散列的重复数据删除特征,这也是区分大小写的。 uniq
的代码如下所示:
sub uniq {
my %seen = ();
grep { not $seen{$_}++ } @_;
}
如果您想直接在自己的代码中使用此子代码,可以在其中加入lc
:
sub uniq_no_case {
my %seen = ();
grep { not $seen{$_}++ } map lc, @_;
}
解释这是如何工作的:
@_
包含子例程的args,它们被送入grep
语句。通过代码块时返回true的任何元素都由grep语句返回。代码块由几个更精细的点组成:
$seen{$_}++
在第一次看到元素时返回0。该值仍然会增加到1,但在返回之后(与首先出现的++$seen{$_}
相反,然后返回)。grep
作为sub中的最后一个语句将返回一个列表,该列表又由子返回。map lc, @_
只是将lc
函数应用于@_
中的所有元素。答案 1 :(得分:6)
使用哈希来跟踪您已经看过的单词,但也可以将它们标准化为大写/小写:
my %seen;
my @unique;
for my $w (@words) {
next if $seen{lc($w)}++;
push(@unique, $w);
}
# @unique has the unique words
请注意,这将保留原始单词的大小写。
更新:如评论中所述,目前尚不清楚OP需要什么,但我用这种方式编写了解决方案,以说明在某种“等价关系”下从列表中选择唯一代表的一般技术。在这种情况下,当且仅当$a
时,等价关系是单词$b
等同于单词lc($a) eq lc($b)
。
大多数等价关系可以用这种方式表示,也就是说,关系是由分类器函数f()
定义的,这样$a
等同于$b
当且仅当f($a) eq f($b)
1}}。例如,如果我们想要说两个单词长度相同,那么f()
就是length()
。
所以现在您可能会看到为什么我以这种方式编写算法 - 分类器函数可能不会生成属于原始列表的值。在f = length
的情况下,我们想要选择单词,但单词的f
是一个数字。