#perl #indexing
#perl #индексирование
Вопрос:
Я пытаюсь написать небольшую программу, которая берет из командной строки файлы и выводит количество встречаемости слова из всех файлов и в каком файле оно встречается. Кажется, что первая часть, определяющая количество встречаемости слова, работает хорошо.
Однако я затрудняюсь со второй частью, а именно с поиском, в каком файле (т. Е. имени файла) встречается это слово. Я подумываю об использовании массива, в котором хранится слово, но не знаю, лучший ли это способ или какой самый лучший способ. Это код, который у меня есть на данный момент, и, похоже, он хорошо работает для той части, которая подсчитывает, сколько раз слово встречается в данном файле (ах):
use strict;
use warnings;
my %count;
while (<>) {
my $casefoldstr = lc $_;
foreach my $str ($casefoldstr =~ /w /g) {
$count{$str} ;
}
}
foreach my $str (sort keys %count) {
printf "$str $count{$str}:n";
}
Комментарии:
1. Я исправил отступ в вашем коде. Я постоянно удивляюсь, как много людей пытаются писать код с кажущимися случайными отступами!
2.
perltidy -pbp
фтв!3. Это очень помогло бы, если бы вы показали тот результат, который вы хотели.
Ответ №1:
Доступ к имени файла осуществляется через $ARGV
.
Вы можете использовать это для создания вложенного хэша с именем файла и словом в качестве ключей:
use strict;
use warnings;
use List::Util 'sum';
while (<>) {
$count{$word}{$ARGV} for map lc, /w /g;
}
foreach my $word ( keys %count ) {
my @files = keys %$word; # All files containing lc $word
print "Total word count for '$word': ", sum( @{ $count{$word} }{@files} ), "n";
for my $file ( @files ) {
print "$count{$word}{$file} counts of '$word' detected in '$file'n";
}
}
Комментарии:
1. Каким должен быть результат, если один и тот же файл предоставляется дважды?
2. @reinierpost если один и тот же файл будет предоставлен дважды, количество слов для этого файла удвоится. Этот конкретный сценарий (и вызывающий удивление?) может быть смягчен предварительной обработкой
@ARGV
до того, как он попадет вwhile
цикл:use List::Util qw(sum uniq); BEGIN { @ARGV = uniq @ARGV }
3. Или путем печати и очистки хэша на
eof
.
Ответ №2:
Использование массива кажется разумным, если вы не посещаете ни один файл более одного раза — тогда вы всегда можете просто проверить последнее значение, сохраненное в массиве. В противном случае используйте хэш.
#!/usr/bin/perl
use warnings;
use strict;
my %count;
my %in_file;
while (<>) {
my $casefoldstr = lc;
for my $str ($casefoldstr =~ /w /g) {
$count{$str};
push @{ $in_file{$str} }, $ARGV
unless ref $in_file{$str} amp;amp; $in_file{$str}[-1] eq $ARGV;
}
}
foreach my $str (sort keys %count) {
printf "$str $count{$str}: @{ $in_file{$str} }n";
}