简体   繁体   English

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

[英]How do I print unique elements in Perl array?

I'm pushing elements into an array during a while statement. 我在while语句中将元素推送到数组中。 Each element is a teacher's name. 每个元素都是教师的名字。 There ends up being duplicate teacher names in the array when the loop finishes. 当循环结束时,最终在数组中出现重复的教师名称。 Sometimes they are not right next to each other in the array, sometimes they are. 有时它们在阵列中并不是彼此相邻,有时它们是。

How can I print only the unique values in that array after its finished getting values pushed into it? 如何在完成获取值后才能打印该数组中的唯一值? Without having to parse the entire array each time I want to print an element. 每次我想要打印元素时都不必解析整个数组。

Heres the code after everything has been pushed into the array: 在将所有内容推入数组后继承代码:

$faculty_len = @faculty;
$i=0;
while ($i != $faculty_len)
{
        printf $fh '"'.$faculty[$i].'"';
        $i++;
}   
use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}

Your best bet would be to use a (basically) built-in tool, like uniq ( as described by innaM) . 您最好的选择是使用(基本上)内置工具,如uniq( 如innaM所述)

If you don't have the ability to use uniq and want to preserve order, you can use grep to simulate that. 如果您无法使用uniq并希望保留顺序,则可以使用grep来模拟它。

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

This first gives you a hash where each key is each entry. 这首先给你一个散列,每个键是每个条目。 Then, you iterate over each element, counting how many of them there are, and adding the first one. 然后,迭代每个元素,计算它们中的元素数量,并添加第一个元素。 (Updated with comments by brian d foy) (更新了brian d foy的评论)

I suggest pushing it into a hash. 我建议把它推到哈希。 like this: 像这样:

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

This question is answered with multiple solutions in perldoc. perldoc中的多个解决方案都回答了这个问题。 Just type at command line: 只需键入命令行:

perldoc -q duplicate
@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

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

print "@array1\n"; 

Please note: Some of the answers containing a hash will change the ordering of the array. 请注意:包含散列的一些答案将改变数组的顺序。 Hashes dont have any kind of order, so getting the keys or values will make a list with an undefined ordering. 哈希没有任何类型的顺序,因此获取键或值将使列表具有未定义的顺序。

This doen't apply to grep { ! $seen{$_}++ } @faculty 这不适用于grep { ! $seen{$_}++ } @faculty grep { ! $seen{$_}++ } @faculty

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

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

Just another way to do it, useful only if you don't care about order : 只是另一种方法, 只有在不关心订单时才有用:

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

If you want to avoid declaring a new variable, you can use the somehow underdocumented global variable %_ 如果你想避免声明一个新的变量,你可以使用不知何故的未记录的全局变量%_

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

I just found hackneyed 3 liner, enjoy 我刚刚发现了3个班轮,享受

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

If you need to process the faculty list in any way, a map over the array converted to a hash for key coalescing and then sorting keys is another good way: 如果您需要以任何方式处理教师列表,则将数组上的映射转换为用于键合并然后排序键的散列是另一种好方法:

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

You process the list by changing the /.*/ regex for selecting or parsing and capturing accordingly, and you can output one or more mutated, non-unique keys per pass by making ($_,1):() arbitrarily complex. 您可以通过更改/.*/ regex来选择或解析并相应地捕获列表来处理列表,并且您可以通过使($_,1):()任意复杂来输出每个传递的一个或多个变异的非唯一键。

If you need to modify the data in-flight with a substitution regex, say to remove dots from the names ( s/\\.//g ), then a substitution according to the above pattern will mutate the original @faculty array due to $_ aliasing. 如果你需要使用替换正则表达式来修改数据中的数据,比如从名称中删除点( s/\\.//g ),那么根据上述模式的替换会因为$_而改变原始的@faculty数组$_别名。 You can get around $_ aliasing by making an anonymous copy of the @faculty array (see the so-called "baby cart" operator ): 您可以通过制作@faculty数组的匿名副本来解决$_别名(请参阅所谓的“婴儿推车”操作员 ):

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

In more recent versions of Perl, you can pass keys a hashref, and you can use the non-destructive substitution: 在更新的Perl版本中,您可以传递keys hashref,并且您可以使用非破坏性替换:

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

Otherwise, the grep or $seen[$_]++ solutions elsewhere may be preferable. 否则,其他地方的grep$seen[$_]++解决方案可能更可取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM