Как это:
#!/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 "убийцы особенности. В приведенном выше примере у нас есть два, потому что вы хотите подсчитать две разные вещи: вхождения в первую очередь и вхождения каждого из подэлементов в этот префикс письма.
Так мы бежим через каждую строку DATA
(вы, вероятно, хотите использовать реальный дескриптор здесь).
Мы используем split
, чтобы превратить линию в массив, ограниченный пробелами.
Мы назначаем первый элемент $term
и все остальное на линии в @things
.
перечислить список @things
и обновить общий счетчик в пределах определенной буквы, а также префикс/букву %count_elements_of
хэш.
И затем мы перебираем ключи наших хешей (сортируем их) и печатаем результаты.
То, что мы не делаем в приведенном выше, - это ручка, которая полностью пропускает ключи, особенно хорошо. Если вы хотите это сделать, вы больше не можете использовать keys
на хеше, потому что «нет» - это «неопределенный».
Так вместо этого, вам нужно:
#!/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";
}
Это будет «создать» список всех вещей, которые, возможно, потребуется печать в %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) {
и т.д.
tha nks много. Работает !! Как насчет раскола, если мы имеем данные с разделителями \ t? –
'split' по умолчанию означает« любые пробелы ». http://perldoc.perl.org/functions/split.html, чтобы он работал для вкладок. Но если вы хотите использовать _just_ tabs, то 'split/\ t /;' будет делать трюк. – Sobrique
Теперь я хочу только цифры, а не имя вещи. Что мне нужно сделать ?? –