我正在寻找一个参议员的帮助。
要求:
通过一些验证,我在一个数组中追踪了各种值。
@array_name = ("Rajesh","Raju","Ram","John","peter");
现在我从某些背景知道“Rajesh”,“Ram”,“peter”,是重复的条目所以我希望我的输出是:
@array_name = ("Rajesh","Raju","John");
# or
@array_name = ("Ram","Raju","John");
# or
@array_name = ("peter","Raju","John");
我已经完成了如下的示例程序,但它并不能让我满意......
my $spcific_output ="";
my $output ="";
foreach my $name (@array_name)
{
if($name eq "Rajesh" || $name eq "Ram" || $name eq "peter")
{
$spcific_output = "Rajesh and Ram and peter");
}
else
{
$output .= "My Name is $name";
}
}
$output .= $spcific_output;
实现这一目标的最佳途径是什么?
答案 0 :(得分:2)
如果您使用的是v5.10或更高版本,则可以在具有重复名称的阵列上使用智能匹配:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my @names = qw(Rajesh Raju Ram John Peter);
my @dupl = qw(Rajesh Ram Peter);
my $seen;
my @names = grep {$_ ~~ @dupl ? !$seen++ : 1} @names;
print Dumper \@names;
输出:
$VAR1 = [
'Rajesh',
'Raju',
'John'
];
如果grep
中的名称位于!$seen++
,则@names
中的条件会评估@dupl
,并且仅当$_
为0时才会保留$seen
。否则1
(true
)将被评估并保留$_
。
答案 1 :(得分:2)
使用Perl,只要您想要某些集合中的唯一值,请考虑如何使用哈希来帮助您自动折叠重复项,或者至少帮助您记住您已经看过的值。例如,请参阅Perl常见问题解答第4部分中的How can I get the unique keys from two hashes?。
您的案例有点棘手,因为您有一组可互换的名称,因此您必须记录此信息。
sub add_names {
my $equivalent = shift;
for (@_) {
my @names = map lc, @$_;
for (@names) {
die "$0: overlap on name '$_'" if exists $equivalent->{$_};
$equivalent->{$_} = \@names;
}
}
$equivalent;
}
这里,$equivalent
是对哈希的引用。致电后
add_names $equivalent, [ qw/ Rajesh Ram peter / ];
哈希将包含密钥'rajesh'
,'ram'
和'peter'
,其值均为[ 'rajesh', 'ram', 'peter' ]
。以这种方式构建它意味着无论我们首先遇到哪个名称,我们都可以获得完整的名称。
另请注意,您可以在一次调用中堆叠多组名称,如
add_names $equivalent, [ qw/ Rajesh Ram peter / ],
[ qw/ Jim Bob Bubba / ];
使用映射的名称,我们现在可以处理列表并保留我们找到的每个集合的名字。对于给定的名称,请检查我们之前是否已经看过它或它的任何等价物。如果我们还没有看到它,请保存名称并标记所有等价物。
sub remove_duplicates {
my $equivalent = shift;
my %seen;
my @uniques;
foreach my $name (@_) {
my $normal = lc $name;
unless ($seen{$normal}) {
push @uniques, $name;
++$seen{$_} for @{ $equivalent->{$normal} };
}
}
wantarray ? @uniques : \@uniques;
}
底部的wantarray
位是一个常见的Perl习惯用法,用于使返回值适应调用上下文。如果调用者想要一个数组,我们返回数组。如果没有,我们返回一个标量,即对我们的唯一名称数组的引用。
将所有内容组合在一起
my $equivalent = {};
add_names $equivalent, [qw/ Rajesh Ram peter /];
my @array_name = ("Rajesh","Raju","Ram","John","peter");
print $_, "\n" for remove_duplicates $equivalent, @array_name;
输出:
Rajesh Raju John