2017-05-02 2 views
1

タプルキーで辞書を使ってアルゴリズムを実装しましたが、アルゴリズムは動作しますが、非常に遅いです。私は弦のセットを持っています。私はA["abc","bcde"] = 2という2つの文字列の重なりの量を表す連想行列を実装しようとしていました。 LのタプルはAのキーです。Lはソートされた配列です。> A [L [i]] < A [L [i + 1]] 2つの文字列をセット内で最も重複してマージしてから更新します「マトリクス」とLリスト。セットが1つだけの要素になるまで私はループでそれを行います。私の問題は、辞書のアルゴリズムが遅すぎるということです。これを行うより効率的な方法はありますか?ここに私のコードです:C#の連想マトリックスの方が効率的ですか?

List<string> words = new List<string>(wordsFromFile); 

Dictionary<Tuple<string, string>, int> A = new Dictionary<Tuple<string, string>, int>(); 
List<Tuple<string, string>> L = new List<Tuple<string,string>>(); 

(私は行列をリフレッシュその後L.を作るためのソートを数える使用し、リストは非常に時間がかかる:)

  while (words.Count > 1) 
      { 
       string LastItem1 = L.Last().Item1; 
       string LastItem2 = L.Last().Item2; 
       words.Remove(LastItem1); 
       words.Remove(LastItem2); 
       string newElement = merge(LastItem1, LastItem2); 
       words.Add(newElement); 
       for (int i = 0; i < words.Count; ++i) 
       { 
        if (words[i] == newElement) 
        { 
         Tuple<string, string> tmp = new Tuple<string, string>(newElement, newElement); 
         A[tmp] = 0; 
        } 
        else 
        { 
         Tuple<string, string> tmp = new Tuple<string, string>(newElement, words[i]); 
         A[tmp] = A[new Tuple<string, string>(LastItem2, words[i])]; 
         tmp = new Tuple<string, string>(words[i], newElement); 
         A[tmp] = A[new Tuple<string, string>(words[i], LastItem1)]; 
        } 
       } 
       var itemsToRemove = A.Where(f => f.Key.Item1 == LastItem1 || f.Key.Item1 == LastItem2 || f.Key.Item2 == LastItem1 || f.Key.Item2 == LastItem2).ToArray(); 
       foreach (var item in itemsToRemove) 
        A.Remove(item.Key); 

       L.Remove(L.Last()); 
       for (int i = 0; i < L.Count(); ++i) 
       { 
        if (L[i].Item1 == LastItem2 && L[i].Item2 != LastItem1 && L[i].Item2 != newElement && L[i].Item2 != LastItem2) L[i] = new Tuple<string, string>(newElement, L[i].Item2); 
        else if (L[i].Item2 == LastItem1 && L[i].Item1 != LastItem1 && L[i].Item1 != newElement && L[i].Item1 != LastItem2) L[i] = new Tuple<string, string>(L[i].Item1, newElement); 
       } 

       var listitemsToRemove = L.Where(f => f.Item1 == LastItem1 || f.Item2 == LastItem2 || f.Item1 == LastItem2 || f.Item2 == LastItem1).ToArray(); 
       foreach (var item in listitemsToRemove) L.Remove(item); 
       listitemsToRemove = L.Where(f => f.Item2 == LastItem2).ToArray(); 

      } 
+0

辞書は驚くほど速いです、それをアップになります[I](非効率的にforeachループと比較して)3つのルックアップを行っています、。 – Dessus

+0

本当に[mcve]を投稿してください。 – Enigmativity

答えて

0
  1. その非常に読みにくいです難読化コードは、私に飛び出ししかし、一つのことはこれです:

    L [i]は、サブOである.Item1

    辞書と比較してptimal。私はあなたが順序を保持したいと思うかもしれないと思います。その場合、OrderedDictionaryを使うことができます。

  2. あなたのケースではforeachループで最適化できるforループを使います。 forループは生のパフォーマンスが速いが、使用している方法ではありません。あなたはリストであるLについて約12回のルックアップを行います。その配列、そのリストではないので、そのようなリストの途中でアイテムを選ぶことは、時間の経過とともにスピードを落とすことになります。 Foreachはこの特定のケースに合わせて最適化されており、リストを反復する場合にはより高速に対処します(forループが高速なintカウンタを導入しない限り)。

  3. 言葉あなたの問題ではありません、それは一度

+1

'List'は基本的に配列で、おそらくあなたは' LinkedList'と混同していたでしょうか?特に、あなたは「記憶によってリンクされたリストに従う」ことについて話しているからです。ここには何もありません。 –

+0

はい、あなたは正しいです。私は答えを修正します – Dessus

+0

あなたの箇条書き#2もそうではないとは言っても、リンクされたリストを議論しているようです。 –

関連する問題