使用Perl计算文本文件中的唯一项

使用Perl计算文本文件中的唯一项,perl,unique,Perl,Unique,我有一个文本文件,上面列出了数千个名字——名字|姓氏。有没有关于如何使用Perl只计算唯一的姓氏的示例 我已经在使用$count++进行标准计数,以获得总计,但我仍然需要知道一个唯一的计数 谢谢你的建议 只需使用散列来跟踪值,然后在末尾计数: perl -lne ' my ($ln) = (split /\s*\|\s*/)[1]; $h{$ln}++; END { print scalar keys %h } ' file.txt 你想要的是一本字典。您可以

我有一个文本文件,上面列出了数千个名字——名字|姓氏。有没有关于如何使用Perl只计算唯一的姓氏的示例

我已经在使用$count++进行标准计数,以获得总计,但我仍然需要知道一个唯一的计数


谢谢你的建议

只需使用散列来跟踪值,然后在末尾计数:

perl -lne '
     my ($ln) = (split /\s*\|\s*/)[1];
     $h{$ln}++;
     END { print scalar keys %h }
  ' file.txt

你想要的是一本字典。您可以一行一行地(可能在while循环中)读取这些行,删除换行符,然后按管道字符拆分,这样就有了一个变量,比如说
$lastname
,它包含您想要的字段

然后,执行以下操作:
$count{$lastname}++

请注意,
$count{$lastname}
$count
完全无关;这是一个单独的变量


循环完成后,您可以遍历每个lastname:
foreach$lastname(键(%count)){…
并打印出
$lastname
$count{$lastname}

标准方法是使用散列(关联数组)其键是要计数的字符串。由于哈希最多只包含一个给定键,因此可以对不同的字符串进行计数。例如:

my @input_list = ('a', 'b', 'a', 'b', 'a');
my %result_hash;
foreach my $val (@input_list) {
    ++$result_hash{$val};
}
# %result_hash is now (a => 3, b => 2)
print scalar keys %result_hash; # prints '2' (the number of keys)

因为散列的键总是唯一的,所以我建议您可以将元素(在集合中应该是唯一的)作为散列的键。 在您的例子中,使用以姓氏为键的散列来删除重复的姓氏,并计算拥有每个姓氏的人数

$nameList=['Eric|Johnson',
            'Herbert|Schildt',
            'Carl|Schildt',
            'Rose|Johnson',
            'Allen|Johnson',];
$nameHash={};
map {$_=~/\|(\w+)/; $nameHash->{$1}+=1;} @{$nameList};
# read the string behind "|"
# subsequently, make this string the key of hash
# increase the value of this key to count the number of people having this last name
map {print "$_: $nameHash->{$_} people\n"} keys %{$nameHash};
然后,你可以得到这样的结果

Johnson: 3 people
Schildt: 2 people

总之,只要你想要一套,随时都可以调用哈希。干杯!

另一种方法,希望可读性更好一些:

#!/usr/bin/perl
use strict;
use warnings;

my %names = ();
while (  my $name = <DATA>)
{
     chomp($name);
     my ($fname, $lname) = split(/\|/, $name);
     if (exists($names{$lname}))
     {
       $names{$lname} += 1;
     }
     else
     {
       $names{$lname} = 1;
     }

}

foreach my $name (sort { $names{$b} <=> $names{$a} } keys %names) {
  printf "%s: %s\n", $name, $names{$name};
}

print "Unique Names: " . scalar keys(%names) . "\n";

__DATA__
Rosetta|Drayer
Celinda|Blaylock
Twana|Riner
Mike|Riner
Bob|Riner
Linda|Riner
Liliana|Littlejohn
John|Littlejohn
Candance|Candanoza
Brian|Candanoza
George|Candanoza
Noreen|Frandsen
Nakisha|Feltmann
Vanetta|Feltmann
Lorretta|Feltmann
Domenic|Feltmann
Madalene|Feltmann
Rosalinda|Feltmann
Brandie|Feltmann
Nu|Feltmann
Tennille|Feltmann

这是使用uniq函数的另一种方法:

#!/usr/bin/perl
use strict;
use warnings;

use List::MoreUtils 'uniq';


my @names = ();
while (  my $name = <DATA>)
{
     chomp($name);
     my ($fname, $lname) = split(/\|/, $name);
     push(@names, $lname);
}

my @uniq = uniq @names;
print "Unique Names: " . scalar @uniq . "\n";

__DATA__
Rosetta|Drayer
Celinda|Blaylock
Twana|Riner
Mike|Riner
Bob|Riner
Linda|Riner
Liliana|Littlejohn
John|Littlejohn
Candance|Candanoza
Brian|Candanoza
George|Candanoza
Noreen|Frandsen
Nakisha|Feltmann
Vanetta|Feltmann
Lorretta|Feltmann
Domenic|Feltmann
Madalene|Feltmann
Rosalinda|Feltmann
Brandie|Feltmann
Nu|Feltmann
Tennille|Feltmann

谢谢你的回答。我已经试过了代码,但是当按键打印出来时,它只是一系列的1,并且它正在计算每个项目,而不仅仅是唯一的项目。你知道我做错了什么吗?代码“my@input\u list=(@fieldsagain[1]);my%result\u hash;foreach my$val(@input\u list){++$result\u hash{$val}#%result_散列现在是(a=>3,b=>2)打印标量键%result_散列;#打印“2”(键数)“代码”@ USE1681502:这听起来像是每循环迭代一次运行这个代码,并简单地计算每行中不同的值的数量。因为每行包含一个不同的值,这显然会给您一个完整的<代码> 1代码/代码>。所以,让我们后退一步。您明白我发布的例子吗?如果是,那么您应该能够将其逻辑应用到您自己的案例中。如果没有,那么请指出您不理解的内容。谢谢。我实际上在If语句中有它,因为报告打开文件并提取在日期范围之间输入的名称列表,我只需要它计数唯一。当我将数组打印到屏幕上时,我可以看到所有的names.所以,我不确定我遗漏了什么。我真的很感谢你的帮助。@user1681502:我也不确定你遗漏了什么。在你之前的评论中,你有
@input\u list=(@fieldsagain[1])
,后面跟着code来计算
@input\u list
。因为
(@fieldsagain[1])
是一个单元素列表,该计数自然为
1
。如果我不包括[1],它如何知道该按哪个字段计数?我试着只使用@fieldsagain,它计算了每一行。非常感谢您花时间回答。我想可能我问的问题不正确。我实际上在寻找的是唯一名称的总数。因此,在您的示例中,它将是7,因为有七个唯一的名称。您能回答吗你告诉我如何调整你的示例以获得它?我可以在foreach循环中使用计数吗?非常感谢!没问题。只需将此添加到结尾:打印“唯一名称:”.scalar Key(%Names)。“\n”;输出:唯一名称:7谢谢。我已经打开并读取了文本文件。姓氏在@fieldsagain[1]中。我尝试使用了(我的$name=@fieldsagain[1]),我又得到了1。如果我使用while(我的$name=@fieldsagain),我只得到了一个总行数。如果你在问题中包含它(或至少相关部分),那么在你已有的代码周围找到一个答案会更容易
#!/usr/bin/perl
use strict;
use warnings;

use List::MoreUtils 'uniq';


my @names = ();
while (  my $name = <DATA>)
{
     chomp($name);
     my ($fname, $lname) = split(/\|/, $name);
     push(@names, $lname);
}

my @uniq = uniq @names;
print "Unique Names: " . scalar @uniq . "\n";

__DATA__
Rosetta|Drayer
Celinda|Blaylock
Twana|Riner
Mike|Riner
Bob|Riner
Linda|Riner
Liliana|Littlejohn
John|Littlejohn
Candance|Candanoza
Brian|Candanoza
George|Candanoza
Noreen|Frandsen
Nakisha|Feltmann
Vanetta|Feltmann
Lorretta|Feltmann
Domenic|Feltmann
Madalene|Feltmann
Rosalinda|Feltmann
Brandie|Feltmann
Nu|Feltmann
Tennille|Feltmann
Unique Names: 7