我有一个像这样的输入文件(3列数据)。每行中也存在不同的条目..对应于... b ..和c ...
a sk asd
a sk lsd
a mk wsd
a lk asd
a lk lsd
a pk wsd
a pk asd
b sk lsd
b sk wsd
b mk asd
b lk lsd
b lk wsd
c sk asd
c sk lsd
c mk wsd
c lk asd
c lk lsd
d sk wsd
d sk asd
d mk lsd
我想编写一个perl程序,首先计算a,b,c和d。然后计算对应于a,b,c和d的每个条目。
输出将是这样的..
a=7 sk=2 mk=1 lk=2 pk=2 asd=3 lsd=2 wsd=2
b=5 sk=2 mk=1 lk=2 pk=0 asd=1 lsd=2 wsd=2
c=5 sk=2 mk=1 lk=2 pk=0 asd=2 lsd=2 wsd=1
d=3 sk=2 mk=1 lk=0 pk=0 asd=1 lsd=1 wsd=1
我怎么能做到这一点。请帮帮忙?
答案 0 :(得分:1)
像这样:
#!/usr/bin/perl
use strict;
use warnings;
my %count_elements_of;
my %count_of;
while (<DATA>) {
my ( $term, @things ) = split;
$count_of{$term}++;
foreach my $thing (@things) {
$count_elements_of{$term}{$thing}++;
}
}
foreach my $term ( sort keys %count_elements_of ) {
print "$term => $count_of{$term}, ";
foreach my $thing ( sort keys %{ $count_elements_of{$term} } ) {
print "$thing => $count_elements_of{$term}{$thing}, ";
}
print "\n";
}
__DATA__
a sk asd
a sk lsd
a mk wsd
a lk asd
a lk lsd
a pk wsd
a pk asd
b sk lsd
b sk wsd
b mk asd
b lk lsd
b lk wsd
c sk asd
c sk lsd
c mk wsd
c lk asd
c lk lsd
d sk wsd
d sk asd
d mk lsd
将打印:
a => 7, asd => 3, lk => 2, lsd => 2, mk => 1, pk => 2, sk => 2, wsd => 2,
b => 5, asd => 1, lk => 2, lsd => 2, mk => 1, sk => 2, wsd => 2,
c => 5, asd => 2, lk => 2, lsd => 2, mk => 1, sk => 2, wsd => 1,
d => 3, asd => 1, lsd => 1, mk => 1, sk => 2, wsd => 1,
要解释 - 你需要的是哈希,这实际上是perl&#39;杀手级功能之一。我们在上面的例子中有两个,因为你想计算两个不同的东西 - 第一个字母的出现,以及该字母前缀中每个子元素的出现。
所以我们遍历DATA
的每一行(你可能想在这里使用一个真正的文件句柄)。
我们使用split
将行转换为数组,以空格分隔。
我们将第一个元素分配给$term
,并将该行中的所有其他内容分配到@things
。
迭代@things
列表,并更新特定字母内的总计数,以及每个前缀/字母%count_elements_of
哈希值。
然后我们迭代哈希的键(对它们进行排序)并打印结果。
我们在上面做的不是特别好地处理完全丢失的键。如果你想这样做,你就不能再在哈希上使用keys
- 因为&#39;不存在&#39;未定义&#39;。
相反,你需要:
#!/usr/bin/perl
use strict;
use warnings;
my %count_elements_of;
my %count_of;
my %all_sub_elements;
while (<DATA>) {
my ( $term, @things ) = split;
$count_of{$term}++;
foreach my $thing (@things) {
$count_elements_of{$term}{$thing}++;
$all_sub_elements{$thing}++;
}
}
foreach my $term ( sort keys %count_elements_of ) {
print "$term => $count_of{$term}, ";
foreach my $thing ( sort keys %all_sub_elements ) {
print "$thing => ", $count_elements_of{$term}{$thing} // 0," ";
}
print "\n";
}
这将构建&#39;在%all_sub_elements
中可能需要打印的所有内容的列表,我们稍后会使用它来确定要输出的内容。我们使用//
运算符,这是一个条件类似到||
(逻辑或),但用于defined
。在这种情况下它没有太大的区别,但我认为在正常操作哈希时它是一个有用的区别。 (因为值为零的哈希值与具有缺失值的哈希值相同)。
然后打印:
a => 7, asd => 3 lk => 2 lsd => 2 mk => 1 pk => 2 sk => 2 wsd => 2
b => 5, asd => 1 lk => 2 lsd => 2 mk => 1 pk => 0 sk => 2 wsd => 2
c => 5, asd => 2 lk => 2 lsd => 2 mk => 1 pk => 0 sk => 2 wsd => 1
d => 3, asd => 1 lk => 0 lsd => 1 mk => 1 pk => 0 sk => 2 wsd => 1
你可以 - 或者 - 定义一个数组:
my @output_order = qw ( sk lk mk asd lsd wsd );
如果您愿意,可以使用它来输出您的输出:
foreach my $thing ( @output_order ) {
等