web-dev-qa-db-ja.com

C#でList <>の重複を回避する高速な方法

私のC#プログラムは、指定されたパターンからランダムな文字列を生成します。これらの文字列はリストに保存されます。重複は許可されていないため、次のようにしています:

List<string> myList = new List<string>();
for (int i = 0; i < total; i++) {
  string random_string = GetRandomString(pattern);
  if (!myList.Contains(random_string)) myList.Add(random_string);
}

ご想像のとおり、これは数百のエントリに対して正常に機能します。しかし、私は数百万の文字列を生成する状況に直面しています。また、文字列を追加するたびに重複のチェックが遅くなります。

重複を避けるためのより速い方法はありますか?

28
Robert Strauch

アイテムが存在するかどうかをはるかに効率的に判断できるデータ構造、つまりHashSetを使用します。セット内のアイテムの数に関係なく、アイテムが一定の時間内にセット内にあるかどうかを判別できます。

really代わりにListのアイテムが必要な場合、または結果リストのアイテムを生成順に並べる必要がある場合は、両方のデータを保存できます。リストとハッシュセット。現在HashSetに存在しない場合、両方のコレクションにアイテムを追加します。

44
Servy

List<>を使用しないでください。代わりにDictionary<>またはHashSet<>を使用してください!

9
catfood

最も簡単な方法はこれを使用することです:

myList = myList.Distinct().ToList();

これには、リストを一度作成してから、新しいリストを作成する必要があります。より良い方法は、事前にジェネレーターを作成することです。

public IEnumerable<string> GetRandomStrings(int total, string pattern)
{
    for (int i = 0; i < total; i++) 
    {
        yield return GetRandomString(pattern);
    }
}

...

myList = GetRandomStrings(total, pattern).Distinct().ToList();

もちろん、インデックスでアイテムにアクセスする必要がない場合は、おそらくToListを削除してIEnumerableを使用するだけで、さらに効率を改善できます。

8
p.s.w.g

順序が重要でない場合は、HashSet<string>を使用できます。

HashSet<string> myHashSet = new HashSet<string>();
for (int i = 0; i < total; i++) 
{
   string random_string = GetRandomString(pattern);
   myHashSet.Add(random_string);
}

HashSetクラスは、高性能なセット操作を提供します。セットは、重複する要素を含まないコレクションであり、要素の順序は特にありません。

[〜#〜] msdn [〜#〜]

または、順序が重要な場合、私は SortedSet (.net 4.5のみ)を使用することをお勧めします

6
DGibbs

良い方法ではありませんが、簡単な修正方法です。リスト全体に重複エントリがあるかどうかを確認するためにboolを使用してください。

bool containsKey;
string newKey;

    public void addKey(string newKey){

         foreach(string key in MyKeys){
           if(key == newKey){
             containsKey = true;
          }
         }

      if(!containsKey){
       MyKeys.add(newKey);
     }else{
       containsKey = false;
     }

    }
1
Amir Javed

ハッシュテーブルは、リストよりもアイテムが存在するかどうかをチェックするより速い方法です。

0
Zdravko Danev

やってみました:

myList = myList.Distinct()
0
jdehlin