Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.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
Perl中不区分大小写的唯一数组元素_Perl_Uniq - Fatal编程技术网

Perl中不区分大小写的唯一数组元素

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

我使用模块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 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语句返回。代码块由几个更精细的点组成:

  • $seen{$\}++
    第一次看到元素时返回0。该值仍然递增为1,但在返回后(与
    +$seen{$\u}
    谁先inc,然后返回相反)
  • 通过对递增的结果求反,我们得到第一个键为true,后续每个键为false。因此,该列表将被删除
  • grep
    作为sub中的最后一条语句将返回一个列表,该列表由sub返回
  • 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