25

我在 while 语句中将元素推入数组。每个元素都是老师的名字。当循环结束时,数组中最终会出现重复的教师姓名。有时它们在阵列中并不相邻,有时它们是相邻的。

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

将所有内容推入数组后,代码如下:

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

10 回答 10

42
use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}
于 2009-01-13T16:48:18.723 回答
33

您最好的选择是使用(基本上)内置工具,例如 uniq (如 innaM 所述)

如果你没有能力使用 uniq 并且想要保留顺序,你可以使用 grep 来模拟它。

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

这首先给你一个散列,其中每个键是每个条目。然后,您遍历每个元素,计算其中有多少,然后添加第一个元素。(由 brian d foy 更新评论)

于 2009-01-13T16:58:37.267 回答
14

我建议将其推入哈希中。像这样:

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);
于 2009-01-13T16:24:00.537 回答
5
@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

@array1 = grep { ! $seen{ $_ }++ } @array1;

print "@array1\n"; 
于 2012-04-02T06:36:13.203 回答
5

这个问题在 perldoc 中有多种解决方案。只需在命令行输入:

perldoc -q duplicate
于 2012-07-25T14:16:10.073 回答
4

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

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

于 2013-10-01T12:46:55.253 回答
3

这是一个单行命令,用于按出现的顺序打印唯一行。

perl -ne '$seen{$_}++ || print $_' fileWithDuplicateValues
于 2011-12-08T01:03:27.210 回答
2

我刚找到陈旧的 3 班轮,享受

my %uniq; 
undef @uniq(@non_uniq_array); 
my @uniq_array = keys %uniq; 
于 2011-11-08T23:49:29.477 回答
2

只是另一种方法,仅当您不关心 order 时才有用:

my %hash;
@hash{@faculty}=1;
my @unique=keys %hash;

如果你想避免声明一个新变量,你可以使用某种未充分记录的全局变量%_

@_{@faculty}=1;
my @unique=keys %_;
于 2013-10-01T13:17:11.323 回答
0

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

my @deduped = sort keys %{{ map { /.*/? ($_,1):() } @faculty }};
print join("\n", @deduped)."\n";

您可以通过更改用于选择或解析和捕获的正则表达式来处理列表,并且您可以通过任意复杂/.*/的方式在每次传递中输出一个或多个变异的、非唯一的键。($_,1):()

如果您需要使用替换正则表达式修改运行中的数据,例如从名称 ( s/\.//g) 中删除点,那么根据上述模式的替换将@faculty由于$_混叠而改变原始数组。您可以$_通过制作数组的匿名副本来解决别名问题@faculty(请参阅所谓的“婴儿车”运算符):

my @deduped = sort keys %{{ map {/.*/? do{s/\.//g; ($_,1)}:()} @{[ @faculty ]} }};
print join("\n", @deduped)."\n";
print "Unmolested array:\n".join("\n", @faculty)."\n";

在更新的 Perl 版本中,您可以传递keyshashref,并且可以使用非破坏性替换:

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

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

于 2014-06-18T05:39:05.747 回答