2012-12-04 5 views
1

값이 가장 큰 값부터 최대 값까지 정렬 한 해시가 있습니다. 상위 5 위를 차지하려면 어떻게해야합니까? 여기에 하나의 가치 만 얻는 것에 관해 언급 한 게시물이있었습니다. 내가 그렇게 그 값이 다시 다음 과정을 배열에 추가하고 해시의 요소를 삭제하고 점점 할 말을 이해값으로 해시에서 상위 키를 얻는 방법

What is the easiest way to get a key with the highest value from a hash in Perl?

?

이렇게 쉬운 방법이 있어야합니다.

내 해시를 % 단어라고합니다.

편집 실제로 질문하지 않고 질문에 답한 코드를 작성했습니다.

+0

코드를 표시하십시오. – edem

+3

''내가 분류 한 해시가 있습니다 .. ''아니오. 해시를 분류 할 수 없습니다. – TLP

+0

아니, 내가 순서대로 인쇄했음을 의미하지만 상위 5 위를 차지하려고한다. –

답변

5

귀하의 질문은 귀하의 해시에서 5 개의 가장 높은 값을 얻는 방법입니다. 당신은이 부호가있다 :

my @keys = sort { 
    $words{$b} <=> $words{$a} 
    or 
    "\L$a" cmp "\L$b" 
} keys %words; 

당신이 당신의 분류 한 해시 열쇠가있는 곳에. 거기에서 5 개의 탑 키를 가져 가라.

my @highest = splice @keys, 0, 5; # also deletes the keys from the array 
my @highest = @keys[0..4];   # non-destructive solution 

또한 코드에 대한 몇 가지 의견 :

open(my $filehandle0, '<', $file0) || die "Could not open $file0\n"; 

오픈이 실패한 이유에 대한 귀중한 정보를 얻을 수 있도록 다이 문에서 오류 메시지 $!을 포함하는 것이 좋습니다.

for (@words) { 
    s/[\,|\.|\!|\?|\:|\;|\"]//g; 
} 

내가 코멘트에서 말했듯이, 당신은 문자 클래스를 대문자로 이스케이프하거나 교대를 사용할 필요가 없습니다. 다음 중 하나를 사용하십시오.

s/[,.!?:;"]//g for @words; #or 
tr/,.!?:;"//d for @words; 

다음 부분은 약간 이상합니다.

my @stopwords; 
while (my $line = <$filehandle1>) { 
    chomp $line; 
    my @linearray = split(" ", $line); 
    push(@stopwords, @linearray); 
} 
for my $w (my @stopwords) { 
    s/\b\Q$w\E\B//ig; 
} 

당신은 파일에서 중지 단어를 읽을 ... 그리고 당신은 $_에서 중지 단어를 삭제 하시겠습니까? 이 시점에서 $_도 사용하고 계십니까? 또한 루프 헤더에 @stopwords 배열을 다시 선언하면 새 배열이 비어 있음을 의미하므로 루프가 실행되지 않습니다. 이 오류는 침묵입니다. 그래서 눈치 채지 못할 수도 있습니다.

my %words = %words_count; 

여기 당신은 다시 사용하지 않을 때문에, 중복 것 같다 %words_count의 사본을 확인하십시오. 큰 해시를 사용하면 성능이 저하 될 수 있습니다.

my $key_count = 0; 
$key_count = keys %words; 

이것은 한 줄로 이루어질 수 있습니다 : my $key_count = keys %words. 내 의견으로는 더 읽기 쉽습니다.

$value_count = $words{$key} + $value_count; 

+= 연산자로 축약 할 수있다 : 당신이 엄격하고 경고를 사용하는 것이 매우 좋은 $value_cont += $words{$key}

.

+0

매우 도움이되었습니다. 당신은 내 질문에 더 많이 대답했습니다. 내 결함을 지적 해주셔서 감사합니다. 내가 읽었거나 온라인으로 보았던 많은 것들을 사용했습니다. 그런 다음 그것을 코드에 적용했습니다.이 프로젝트를 실제로 많이 배웠습니다. 건배 –

+0

환영합니다 – TLP

+0

내 불용어에 대해 무엇이 나쁜지 잘 모르겠지만 –

3

성능이 당신이 절대적으로 살인자의 속도를 필요로하는 경우

(sort {$words{$a} <=> $words{$b}} keys %words)[0..4]) 

는, 선택 정렬 (5) 반복 한 후 종료 큰 문제가없는 경우는 아마 당신을위한 가장 좋은 방법입니다.

my @results; 
for (0..4) { 
    my $maxkey; 
    my $max = 0; 

    for my $key (keys %words){ 
    if ($max < $words{$key}){ 
     $maxkey = $key; 
     $max = $words{$key}; 
    } 
    } 
    push @results, $maxkey; 
    delete $words{$maxkey}; 
} 

say join(","=>@results); 
+0

속도는 실제로 문제가 아니지만 속도에 대해 살펴 보겠습니다. 대규모로 수행하는 작업은 속도가 필요하기 때문에 도움을 주셔서 감사합니다. –

+0

선형 시간 솔루션으로 업데이트되었습니다. – jozefg

1

거기에는 CPAN 모듈 인 Sort::Key::Top이 있습니다. 직선형 인터페이스와 효율적인 XS 구현을 제공합니다.

use Sort::Key::Top qw(rnkeytop); 

my @results = rnkeytop { $words{$_} } 5 => keys %words; 
관련 문제