假设我有一个关键字文件,包含,说“ab”,“ef”,“ab ef”(现实生活:另外数千个条目)。我想查看每个关键字正在发生的页面
page 0
ab
gg
^L
page 1
ab ef
^L
page 2
Ab
ef
[another thousand pages, 2 million words, each ^L separated]
我想回来
ab => [ 0,1,2 ]
ef => [ 1,2 ]
ab ef => [ 1 ]
我知道如何非常低效地完成这项工作。将文件粘贴成长字符串。小写它。将其拆分成页面。对于每个页面,正则表达式每个(小写)关键字条目,以查看它是否出现在页面上。如果是这样,那么在包含我的关键字作为键的哈希的末尾添加页码。并不难,但效率低下。我的算法看起来更像是一种C方法,而不是一种优雅的perl方法。
唉,我想不出更好的选择。我甚至不能首先将主文件读入哈希,因为空格分隔的多词关键词的可能性会使这个不优雅的错误逻辑。也许perl是错误的工具?!
答案 0 :(得分:4)
其他答案采用了不必要的复杂手段。这个问题的关键是要理解我们可以将结束$/
的行设置为我们喜欢的任何内容。 ^L
代表换页\f
。
use strict; use warnings;
use List::MoreUtils qw/uniq/;
my %keywords;
local $/ = "\f"; # set the input record separator (aka. line end) to form feed
while (<>) {
chomp; # remove the \f
my ($page, $body) = split /\n/, $_, 2; # seperate the page header
my $page_no = ($page =~ /([0-9]+)/) ? $1 # extract the page number
: die "Header did not contain a number:\n$page\n";
# split body into lines, and lines into words. Keep only unique KWs:
my @words = uniq map { $_, split } split /\n/, lc $body;
# Map KWs to an array of page №s.
push @{ $keywords{$_} }, $page_no for @words;
}
# Output the data:
use Data::Dumper;
print Dumper \%keywords;
答案 1 :(得分:1)
这对Perl来说非常完美;只是看看它的另一种方式。使用每个关键字,将当前页面添加到该单词的页面列表中。如果这是我们见过的第一个,请创建单词的页面列表。
use strict;
use warnings;
use Data::Dumper;
my %keywords = ();
my $page = 0;
while (<>)
{
chomp; # remove newline
if (/^page \d+$/) # skip "page 0", etc.
{
next;
}
elsif (/^\l$/) # ctrl-L: new page
{
++$page;
}
else
{
my $word = lc($_);
addWord($word);
if ($word =~ /\s/)
{
my @parts = split(/\s+/, $word);
for my $part (@parts)
{
addWord($part);
}
}
}
}
print Dumper(%keywords);
sub addWord
{
my ($word) = @_;
# haven't seen this word? start an empty page list
if (! defined($keywords{$word}))
{
$keywords{$word} = [];
}
# add current page to the word's list
push @{ $keywords{$word} }, $page;
}
打印:
$VAR1 = 'ef';
$VAR2 = [
1,
2
];
$VAR3 = 'gg';
$VAR4 = [
0
];
$VAR5 = 'ab';
$VAR6 = [
0,
1,
2
];
$VAR7 = 'ab ef';
$VAR8 = [
1
];
根据您的样本。
答案 2 :(得分:1)
完美地使用perl。
输出以下内容:
ab => [ 0,1,2 ]
ab ef => [ 1 ]
ef => [ 1,2 ]
gg => [ 0 ]
代码:
#!/usr/bin/env perl
use warnings;
use strict;
main();
1;
sub main {
my $data = {};
my $page = 0;
while (<DATA>) {
chomp;
next if /\A\^L/;
if (/\Apage (\d+)/) {
$page = $1;
} else {
my $line = lc($_);
$data->{$line}->{$page}++;
for (split /\s/, $line) {
$data->{$_}->{$page}++;
}
}
}
for my $keyword (sort keys %$data) {
my @pages = sort {$a <=> $b} keys %{$data->{$keyword}};
print $keyword . ' => [ ' . join(',',@pages) . ' ]' . "\n";
}
}
__DATA__
page 0
ab
gg
^L
page 1
ab ef
^L
page 2
Ab
ef