2013-10-01 3 views
1

"ab", "ef", "ab ef"(실제 : 수천 개 항목)가 포함 된 키워드 파일이 있다고 가정 해 봅시다. 내 각 키워드가실제 색인 --- perl에서 다중 일치

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 ] 

나는 매우 비효율적으로이 작업을 수행하는 방법을 알고 내가 싶어에서 조회 할 수 있습니다. 파일을 긴 문자열로 채 웁니다. 소문자. 그것을 페이지로 나눕니다. 각 페이지에 대해 (소문자로 표시된) 키워드 항목을 정규식으로 페이지에 표시되는지 확인하십시오. 그렇다면 내 키워드를 키로 포함하는 해쉬 끝에 페이지 번호를 추가하십시오. 어렵지는 않지만 고통스럽게 비효율적입니다. 내 알고리즘은 우아한 perl 접근 방식보다는 C 접근 방식에 가깝다.

아아, 더 나은 대안을 생각할 수 없습니다. 공백으로 분리 된 다중 단어 키워드의 가능성으로 인해이 부적절한 나쁜 논리를 만들 수 있기 때문에 기본 파일을 해시로 읽을 수 없습니다.

어쩌면 perl이 잘못된 도구입니까?!

답변

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 
     ]; 

을 기반으로.

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 
4

다른 답변 불필요한 복잡한 수단을 사용 다음

출력합니다. 이 문제의 핵심은 우리가 좋아하는 것으로 끝나는 줄을 $/으로 설정할 수 있다는 것을 이해하는 것입니다. ^L은 양식 피드 \f을 나타냅니다.

+0

유니크 (이상적으로는 본체에만 있음) 전에 lc를 수행해야합니다. – ysth

+0

문제가 해결되지 않는다고 생각합니다. 파일을 구성 단어로 변환하고 각 단어에 페이지 번호를 지정합니다. –

+0

문제가 해결되지 않는다고 생각합니다. 파일을 구성 단어로 변환하고 각 단어에 페이지 번호를 지정합니다. 공백이 포함될 수있는 구를 포함 할 수있는 단어 목록에서 시작하지 않습니다. 더 빨리 할 수 ​​없습니까? my \ @page = split (/ f /, slurp ($ filename)); for my $ pageno (0 .. $ # 페이지) { my \ @wordsonpage = split/[\ n \ s] /, $ page [$ pageno]; {@ {words {$ _}}, \ pagero for \ @wordsonpage } # 이제는 페이지 번호가있는 단어의 해시가 있습니다 –