一意の文字列の効率的なリストC#


86

重複を無視して文字列のリストを保存する最も効率的な方法は何ですか?dict [str] = false;と書くことで、辞書に文字列を挿入するのが最善だと思っていました。キーをリストとして列挙します。それは良い解決策ですか?

回答:


111

.NET 3.5を使用している場合は、HashSetが機能するはずです。

HashSet <(Of <(T>)>)クラスは、高性能のセット操作を提供します。セットは、重複する要素を含まず、要素の順序が特定されていないコレクションです。


5
ただし、HashSetアイテムの順序は失われます。がList提供する機能。
aggsol 2015年

4
追加:便利なソート済みHashSetであるSortedSet <T>もあります。
whoIsRich 2015

また、HashSetにはインデックスを介してアクセスすることはできず、リストとは対照的に列挙子を介してのみアクセスできることに注意してください。
アンドリュー

23

あなたはこのようなことをするように見えることができます

var hash = new HashSet<string>();
var collectionWithDup = new []{"one","one","two","one","two","zero"}; 

// No need to check for duplicates as the Add method
// will only add it if it doesn't exist already
foreach (var str in collectionWithDup)
    hash.Add(str);   

33
HashSetによるContainsチェックは必要ありません。Addメソッドを直接呼び出すだけで、アイテムがすでに存在するかどうかに応じてtrueまたはfalseが返されます。
LukeH 2009年

1
回答を編集して、冗長なContainsへの呼び出しを削除する必要があります。上記の例が機能するために必要なのはこれだけです。varcollectionWithDup= new [] {"one"、 "one"、 "two"、 "one"、 "two"、 "zero"}; var uniqueValues = new HashSet <string>(collectionWithDup);
user3285954 2014

14

これが良い答えであるかどうかはわかりませんが、挿入順序を維持する一意のセットの必要性に直面したとき、HashSetとListを並べて妥協しました。この場合、セットに追加するときは常に、次のようにします。

if(hashSet.Add(item))
    orderList.Add(item);

アイテムを削除するときは、必ず両方から削除してください。したがって、他に何もリストにアイテムを追加していないことを確認できる限り、挿入順の一意のセットがあります。


10

次のようにLinqを使用することもできます。

using System.Linq;

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };

List<string> distinctItems = items.Distinct().ToList();

8

HashSetを使用します。.Contains()をチェックする必要はありません。リストにアイテムを追加するだけで、重複している場合は追加されません。

   HashSet<int> uniqueList = new HashSet<int>();
   uniqueList.Add(1); // List has values 1
   uniqueList.Add(2);  // List has values 1,2
   uniqueList.Add(1);  // List has values 1,2
   Console.WriteLine(uniqueList.Count); // it will return 2

2

これはシステム名前空間の一部ではありませんが、NHibernateでhttp://www.codeproject.com/KB/recipes/sets.aspxのIesi.Collectionsを使用しています。ソートされたセット、辞書セットなどとともに、ハッシュされたセットをサポートしています。NHibernateで使用されて以来、広く使用されており、非常に安定しています。これも.Net3.5を必要としません


2

を使用しない別の解決策を次に示しHashSetます。

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };
var uniqueItems = items.Where((item, index) => items.IndexOf(item) == index);

このスレッドから採用されました: javascript-配列内の一意の値

テスト:

using FluentAssertions;

uniqueItems.Count().Should().Be(3);
uniqueItems.Should().BeEquivalentTo("one", "two", "zero");

ListHashSetおよびのパフォーマンステストSortedSet。100万回の反復:

List: 564 ms
HashSet: 487 ms
SortedSet: 1932 ms

テストソースコード(要点)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.