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

时间:2022-05-27 07:39:45

I'm pushing elements into an array during a while statement. 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.

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

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++;
}   

10 个解决方案

#1


42  

use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}

#2


33  

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评论更新)

#3


14  

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);

#4


5  

@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

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

print "@array1\n"; 

#5


5  

This question is answered with multiple solutions in perldoc. Just type at command line:

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

perldoc -q duplicate

#6


4  

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 {!$ { $ _ } + + } @faculty

#7


3  

This is a one liner command to print unique lines in order it appears.

这是一个线性命令,按显示的顺序打印唯一的行。

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

#8


2  

I just found hackneyed 3 liner, enjoy

我刚找到了三艘陈腐的班轮,好好享受

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

#9


2  

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 %_;

#10


0  

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. You can get around $_ aliasing by making an anonymous copy of the @faculty array (see the so-called "baby cart" operator):

如果需要使用替换regex修改正在运行的数据,比如从名称中删除点(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";

In more recent versions of Perl, you can pass keys a hashref, and you can use the non-destructive substitution:

在最近的Perl版本中,您可以传递密钥a hashref,并且可以使用非破坏性替换:

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

Otherwise, the grep or $seen[$_]++ solutions elsewhere may be preferable.

否则,在其他地方看到的grep或$_ +解决方案可能更可取。

#1


42  

use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}

#2


33  

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评论更新)

#3


14  

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);

#4


5  

@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

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

print "@array1\n"; 

#5


5  

This question is answered with multiple solutions in perldoc. Just type at command line:

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

perldoc -q duplicate

#6


4  

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 {!$ { $ _ } + + } @faculty

#7


3  

This is a one liner command to print unique lines in order it appears.

这是一个线性命令,按显示的顺序打印唯一的行。

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

#8


2  

I just found hackneyed 3 liner, enjoy

我刚找到了三艘陈腐的班轮,好好享受

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

#9


2  

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 %_;

#10


0  

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. You can get around $_ aliasing by making an anonymous copy of the @faculty array (see the so-called "baby cart" operator):

如果需要使用替换regex修改正在运行的数据,比如从名称中删除点(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";

In more recent versions of Perl, you can pass keys a hashref, and you can use the non-destructive substitution:

在最近的Perl版本中,您可以传递密钥a hashref,并且可以使用非破坏性替换:

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

Otherwise, the grep or $seen[$_]++ solutions elsewhere may be preferable.

否则,在其他地方看到的grep或$_ +解决方案可能更可取。