2011-06-28 2 views
1

私はこの基本的な思考プロセスをソートする方法を持っていますが、Perlのパワーを使用せず、しばらくしてどのようにしたいのですか(いくつかの頻度を忘れる)。私はこれを整理するより良い方法があるのだろうかと思っていた。2次元配列で頻度別にソートする方がいいですか?

目的見つかった一致の頻度に基づいて配列を並べ替えます。アレイの

サンプルアレイ

##ADDED 1 to END of EACH ROW, just because my sort forced me too!!! 
my @all_matches = (["chpt10_2", "sent. 2", "alice", "nsubj", "animals", "protect"], 
       ["chpt12_1", "sent. 54", "bob", "nsubj", "cells", "protect"], 
       ["chpt25_4", "sent. 47", "carol", "nsubj", "plants", "protect"], 
       ["chpt34_1", "sent. 1", "dave", "nsubj", "cells", "protect"], 
       ["chpt35_1", "sent. 2", "eli", "nsubj", "cells", "protect"], 
       ["chpt38_1", "sent. 1", "fred", "nsubj", "animals", "protect"], 
       ["chpt54_1", "sent. 1", "greg", "nsubj", "uticle", "protect"] 
      ); 

現在のソート

@all_matches = sort {lc($a->[4]) cmp lc($b->[4])} @all_matches; 

my ($last_word, $current_word, $word_count); 

for my $j (0 .. $#all_matches) { 

    $current_word = $all_matches[$j][4]; 

    if (lc($last_word) eq lc($current_word)) { 
     $word_count++; 
     } 
    else { 
     if ($j != 0) 
     { 
      for (my $k = 1; $k <= $word_count; $k++) 
      { 
       $all_matches[($j-$k)][6] = $word_count; 
      } 
     } 
     $last_word = $current_word; 
     $word_count = 1; 
     } 
} 
@all_matches = sort {$b->[6] <=> $a->[6] || lc($a->[4]) cmp lc($b->[4])} @all_matches; 

通報 all_matchesが渡されたときに6列が1に設定されています!これが行われた理由は、カウント($match->[6])が空白だったことがあるためです。

ボーナス?最後の2つの列が一緒に表示される頻度の回数に一致します(今は2番目の最後の列をチェックするだけです)。このテストケースでは、最後の列はすべて同じですが、実際には末尾に別の接尾辞があります(保護、保護、保護など)。

私はハッシュを使ってみましたが、それがうまくいったと思っていましたが、いくつかのことを無視しました。

ここで私のハッシュを試みました。これが動作しなかった理由はまだあなたを教えてくれませんでした:

my %freq; 
foreach (map{$_->[4]}@results) #feeds in list of animals, cells, uticle, etc. 
{ 
    $freq{lc $_}++; 
} 


@results = sort {$freq{lc $b->[4]} <=> $freq{lc $a->[4]} #freq order 
            or 
         $a->[0] cmp $b->[0]   #text col 0  
       } @results; 
+0

小さな観測:いいえ必要性をあなたの入力はすべて既にlc()されているので、あなたのループの中でlc()を使用します。 – Flimzy

答えて

7

はなぜ発生回数とキーのハッシュを作成し、それを使用しない:

my %counts; 
foreach my $rowref (@all_matches) 
{ 
    $counts{lc($rowref->[4])}++; 
} 

@all_matches = sort { $counts{lc($b->[4])} <=> $counts{lc($a->[4])} || 
         lc($a->[4]) cmp lc($b->[4]) 
        } @all_matches; 

をテスト済み...

#!/usr/bin/env perl 

use strict; 
use warnings; 

my @all_matches = (
    ["chpt10_2", "sent. 2", "alice", "nsubj", "animals", "protect"], 
    ["chpt12_1", "sent. 54", "bob", "nsubj", "cells", "protect"], 
    ["chpt25_4", "sent. 47", "carol", "nsubj", "plants", "protect"], 
    ["chpt34_1", "sent. 1", "dave", "nsubj", "cells", "protect"], 
    ["chpt35_1", "sent. 2", "eli", "nsubj", "cells", "protect"], 
    ["chpt38_1", "sent. 1", "fred", "nsubj", "animals", "protect"], 
    ["chpt54_1", "sent. 1", "greg", "nsubj", "uticle", "protect"] 
    ); 

my %counts; 
foreach my $rowref (@all_matches) 
{ 
    $counts{lc($rowref->[4])}++; 
} 

@all_matches = sort { $counts{lc($b->[4])} <=> $counts{lc($a->[4])} || 
         lc($a->[4]) cmp lc($b->[4]) 
        } @all_matches; 

my $i = 0; 
foreach my $rowref (@all_matches) 
{ 
    $i++; 
    print "$i"; 
    print " $_" foreach (@$rowref); 
    print "\n"; 
} 

出力:

1 chpt12_1 sent. 54 bob nsubj cells protect 
2 chpt34_1 sent. 1 dave nsubj cells protect 
3 chpt35_1 sent. 2 eli nsubj cells protect 
4 chpt10_2 sent. 2 alice nsubj animals protect 
5 chpt38_1 sent. 1 fred nsubj animals protect 
6 chpt25_4 sent. 47 carol nsubj plants protect 
7 chpt54_1 sent. 1 greg nsubj uticle protect 

コメントに記載されているように、データが表示されている場合は、lc操作は不要です。これらを削除すると、各配列に大文字と小文字が変換されたキーが追加されるため、パフォーマンスが向上します。

と行ごとに一度使用lcと - マングドデータ値に注目してください:

#!/usr/bin/env perl 

use strict; 
use warnings; 

my @all_matches = (
    [ "chpt10_2", "sent. 2", "alice", "nsubj", "animAls", "protect" ], 
    [ "chpt12_1", "sent. 54", "bob", "nsubj", "celLs", "protect" ], 
    [ "chpt25_4", "sent. 47", "carol", "nsubj", "plAnts", "protect" ], 
    [ "chpt34_1", "sent. 1", "dave", "nsubj", "cElls", "protect" ], 
    [ "chpt35_1", "sent. 2", "eli", "nsubj", "cells", "protect" ], 
    [ "chpt38_1", "sent. 1", "fred", "nsubj", "Animals", "protect" ], 
    [ "chpt54_1", "sent. 1", "greg", "nsubj", "uticle", "protect" ], 
    ); 

my %counts; 
foreach my $rowref (@all_matches) 
{ 
    push @$rowref, lc($rowref->[4]); 
    $counts{$rowref->[6]}++; 
} 

@all_matches = sort { $counts{$b->[6]} <=> $counts{$a->[6]} || $a->[6] cmp $b->[6] 
        } @all_matches; 

my $i = 0; 
foreach my $rowref (@all_matches) 
{ 
    $i++; 
    print "$i"; 
    printf " %-9s", $_ foreach (@$rowref); 
    print "\n"; 
} 

出力:

1 chpt12_1 sent. 54 bob  nsubj  celLs  protect cells  
2 chpt34_1 sent. 1 dave  nsubj  cElls  protect cells  
3 chpt35_1 sent. 2 eli  nsubj  cells  protect cells  
4 chpt10_2 sent. 2 alice  nsubj  animAls protect animals 
5 chpt38_1 sent. 1 fred  nsubj  Animals protect animals 
6 chpt25_4 sent. 47 carol  nsubj  plAnts protect plants 
7 chpt54_1 sent. 1 greg  nsubj  uticle protect uticle 
+0

より多くのテストから、それぞれの方法に利点があるケースがいくつか見つかりました。あなたの問題は時々です: '$ counts {$ match - > [4]}'を数字として表示すると、実際のマッチが正しい場所に表示されますが、どこにも数字がありません(未初期化値の誤差)?私はこれを調べ続けます。ありがとう...さらなる研究では、単語が大文字で始まる場合に発生することが示されています – Jon

+0

これまで$ counts {lc $ match - > [4]}で印刷することで、そのエラーを排除しました。 – Jon

+1

@Jon:最後の例では、4の代わりに添え字6を使用することでそれを排除することもできます。カウントにアクセスするときに正規の(小文字の)キー値をそこに慎重に(再)使用して保存しました。だからこそ、2回目のフルプログラムは、 '$ counts {$ b - > [4]} 'の代わりに' $ counts {$ b - > [6]} 'を比較します。あなたが一貫している限り、すべてがOKです。 –

1

を、この方法を試してください。

my @all_matches = (["chpt10_2", "sent. 2", "alice", "nsubj", "animals", "protect"], 
     ["chpt12_1", "sent. 54", "bob", "nsubj", "cells", "protect"], 
     ["chpt25_4", "sent. 47", "carol", "nsubj", "plants", "protect"], 
     ["chpt34_1", "sent. 1", "dave", "nsubj", "cells", "protect"], 
     ["chpt35_1", "sent. 2", "eli", "nsubj", "cells", "protect"], 
     ["chpt38_1", "sent. 1", "fred", "nsubj", "animals", "protect"], 
     ["chpt54_1", "sent. 1", "greg", "nsubj", "uticle", "protect"] 
     ); 

my %wordcount; 

foreach my $row (@all_matches) { 
     $wordcount{$row->[4]}++; 
} 

my @sorted = sort { $wordcount{$b->[4]} <=> $wordcount{$a->[4]} } @all_matches; 
+1

カウントが結ばれていると、アルファベット順で確実にソートされません。さもなければ、私と非常によく似ています - 私は、あなたがしなかったオリジナルの 'lc'操作を保存しました。 –

+0

あなたは間違っています。そして、あなたが投稿している間、あなたが最初に書いていた;) –