2017-06-07 3 views
0

私はいくつかの問題をgo mapを最適化しています。
文字列の配列に頻度テーブル(別々の出現を数えます)を生成したいと思います。私のコードは小さな配列に対してうまくいきますが、100k +構造で作業を始めるときには、多くの異なる値があります。go:アレイ内の別個の値を数えます - パフォーマンスのヒント

私のアプローチは、異なる値を持つ配列を生成し、値を比較し、(文字列にマップされた)カウンタ変数を増やすことです。

counter := make(map[string]int)  
    for _, distinct := range distinctStrArray{ 
     for _, row := range StrArray{ 
      if (row == distinct){ 
       counter[distinct]++ 
      } 
     } 
    } 

Iは、入力配列は、以前にソートして(マップの変更の数を最小にする)別のアプローチを試みました。これは少し速いです。

count:=0 
    for _, distinct := range distinctStrArray{ 
     for _, row := range StrArray{ 
      if (row == distinct){ 
       count++ 
      } 
     } 
    counter[distinct] += count 
    count= 0 
    } 

は、あなたが、私はシンプルな数(個別の)タイプの問題を最適化するために何ができるかのいずれかの提案を持っていますか...?私は何でもできる。
ありがとう!

+0

2番目の例では、入力がソートされている場合は不必要な一致を見つけた後も繰り返し処理を続けます。 'row!= distinct && count> 0'の場合、マッチを見つけた後に最初に不一致になり、入力がソートされてもそれ以降一致することはありませんので、ブレークできます。 – Adrian

+0

2つの配列を持つ目的は何ですか?マップはすでに異なるキーを保証しています。 – Adrian

+0

あなたは正しいです - ネストされたループはパフォーマンスを殺していました。マップは私に別個の値を与えました!場合によっては、複雑すぎるものもあります。 – mik

答えて

3

文脈がなければ、個別の値の別々の配列をダンプします。生成には時間がかかり、ネストループが必要になります。あなたには、いくつかの別の目的のためにカウントなしの明確な文字列のリストが必要な場合は、あなたが簡単に後からそれを得ることができ

counter := make(map[string]int)  
for _, row := range StrArray { 
    counter[row]++ 
} 

二番目の配列には他の目的ではありませんと仮定すると、私のようなものを使用したいです
distinctStrings := make([]string, len(counter)) 
i := 0 
for k := range counter { 
    distinctStrings[i] = k 
    i++ 
} 

異なる文字列の配列の反復はO(n)ですが、キーによるマップアクセスはO(log(n))です。それはO(n^2)からO(n * log(n))にあなたの全体を取ります。これは大きなデータセットでは大幅に改善されるはずです。しかし、あらゆる最適化と同様に、テスト、測定、分析、最適化。

+0

ハッシュマップの場合、キーによるマップアクセスは通常O(1)です。 – icza

+0

O(1)... ish? Go仕様では、パフォーマンスに関する記述はありません。私は、「* O(log(n))よりmap accessやO(n * log(n))よりも悪くない」と言いましょう。また、繰り返しのいくつかはルックアップだけでなく、挿入され、リバランスなどの理由でもう少し時間がかかる傾向にあります。... O(n^2)よりも速くなります。 – Adrian

関連する問題