如何在Perl数组中打印唯一元素?

如何在Perl数组中打印唯一元素?,perl,arrays,unique,Perl,Arrays,Unique,我在while语句期间将元素推入数组。每个元素都是一个教师的名字。循环结束时,数组中会出现重复的教师名称。有时它们在数组中不是紧挨着的,有时它们是紧挨着的 在完成将值推入数组后,如何仅打印该数组中的唯一值?无需每次打印元素时都解析整个数组 以下是将所有内容推入阵列后的代码: $faculty_len = @faculty; $i=0; while ($i != $faculty_len) { printf $fh '"'.$faculty[$i].'"'; $i+

我在while语句期间将元素推入数组。每个元素都是一个教师的名字。循环结束时,数组中会出现重复的教师名称。有时它们在数组中不是紧挨着的,有时它们是紧挨着的

在完成将值推入数组后,如何仅打印该数组中的唯一值?无需每次打印元素时都解析整个数组

以下是将所有内容推入阵列后的代码:

$faculty_len = @faculty;
$i=0;
while ($i != $faculty_len)
{
        printf $fh '"'.$faculty[$i].'"';
        $i++;
}   

我建议把它做成一份杂烩。 像这样:

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);

你最好的选择是使用(基本上)内置工具,比如uniq(

如果您没有使用uniq的能力,并且希望保持秩序,那么可以使用grep来模拟

my %seen;
my @unique = grep { ! $seen{$_}++ } @faculty;
# printing, etc.

这首先给你一个散列,其中每个键都是每个条目。然后,你迭代每个元素,计算有多少个元素,然后添加第一个元素。(由brian d foy用注释更新)

我刚找到hackneyed 3 liner,享受吧

my %uniq; 
undef @uniq(@non_uniq_array); 
my @uniq_array = keys %uniq; 

这是一个单行命令,用于按显示顺序打印唯一的行

perl -ne '$seen{$_}++ || print $_' fileWithDuplicateValues

perldoc中有多种解决方案可以回答此问题。只需在命令行中键入:

perldoc -q duplicate

请注意:一些包含哈希的答案将改变数组的顺序。哈希没有任何顺序,因此获取键或值将生成一个未定义顺序的列表


这不适用于grep{!$seen{$}++}@faculty

这只是另一种方法,只有在您不关心顺序的情况下才有用:

如果要避免声明新变量,可以使用文档记录不足的全局变量


如果您需要以任何方式处理教员列表,那么将数组上的映射转换为散列以进行键合并,然后对键进行排序是另一种好方法:

my @deduped = sort keys %{{ map { /.*/? ($_,1):() } @faculty }};
print join("\n", @deduped)."\n";
您可以通过更改
/.*/
正则表达式来处理列表,以进行相应的选择或解析和捕获,并且通过使
($,1):()
任意复杂,每次可以输出一个或多个经过变异的非唯一键

如果需要使用替换正则表达式修改正在运行的数据,可以说从名称中删除点(
s/\.//g
),则根据上述模式进行的替换将由于
$\ucode>别名而使原始
@faculty
数组发生变异。您可以通过制作
@faculty
数组的匿名副本来绕过
$\ucode>别名(参见所谓的:

在较新版本的Perl中,可以传递
一个hashref,并且可以使用非破坏性替换:

my @deduped = sort keys { map { /.*/? (s/\.//gr,1):() } @faculty };

否则,其他地方的
grep
$seen[$\u]+
解决方案可能更可取。

这有时会改变元素的顺序。也许您可以提到将“push@faculty\u unique,$facs除非存在$faculty\u hash{$facs}”放入“push@faculty\u unique,$facs”的可能性在for循环中。我认为对于教师的姓名,顺序并不重要。如果是,则可能是字母顺序。仍然不太难解决。您可以始终“排序键%feculty\u hash”以获得排序(ASCII betically)列表。而不是使用foreach,我会使用map:my%feculty\u hash=map{$\u=>1}@faculty;如果可以安装MoreUtils,则此操作有效。但并不总是如此。列表::MoreUtils是一个没有依赖项的单个模块。如果您使用共享主机,则应该能够拥有该模块的本地副本。我想您的意思是:my%Seen;@unique=grep{!$Seen{$}++@faculty;这是一个与uniq预期效果类似的答案。我把它放在一个函数中:sub uniq{local%\uu;grep{!${${$}++}谢谢各位:)我强烈建议使用
%\uucode>以外的东西。Perl使用
\
变量来实现神奇的事情,
%\
可能是未来的一个变量。这是我最喜欢的答案-快速完成任务,不需要任何额外的软件包。美好的根据Robert P的建议,@ekerner函数包装器的一个清理版本:
subuniq{my%seen;返回grep{!$seen{$}++}
不使用数组,而是使用哈希。我尽可能少地使用数组。数组没有什么问题,只要它们用于它们擅长的领域。:-)
my %hash;
@hash{@faculty}=1;
my @unique=keys %hash;
@_{@faculty}=1;
my @unique=keys %_;
my @deduped = sort keys %{{ map { /.*/? ($_,1):() } @faculty }};
print join("\n", @deduped)."\n";
my @deduped = sort keys %{{ map {/.*/? do{s/\.//g; ($_,1)}:()} @{[ @faculty ]} }};
print join("\n", @deduped)."\n";
print "Unmolested array:\n".join("\n", @faculty)."\n";
my @deduped = sort keys { map { /.*/? (s/\.//gr,1):() } @faculty };