Benzersiz dizelerin verimli listesi C #


86

Yinelenenleri görmezden gelerek bir dizi saklamanın en etkili yolu nedir? Bir sözlüğün dict [str] = false yazarak en iyi dizge eklemek olabileceğini düşünüyordum; ve anahtarlar aracılığıyla bir liste halinde numaralandırma. Bu iyi bir çözüm mü?

Yanıtlar:


111

.NET 3.5 kullanıyorsanız, HashSet sizin için çalışmalıdır.

HashSet <(Of <(T>)>) sınıfı, yüksek performanslı set işlemleri sağlar. Küme, yinelenen öğeler içermeyen ve öğeleri belirli bir sırada olmayan bir koleksiyondur.


6
Ancak bir HashSetöğe sırasını kaybedecektir. Bir özellik a Listsağlar.
aggsol

5
Ek: Ayrıca uygun bir sıralanmış HashSet olan SortedSet <T> vardır.
WhoIsRich

Ayrıca HashSet'e indice aracılığıyla erişilemeyeceğini, yalnızca Listenin aksine bir numaralandırıcı aracılığıyla erişilemeyeceğini unutmayın.
Andrew

23

Bunun gibi bir şey yapmaya bakabilirsin

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 ile Contains kontrolüne ihtiyacınız yoktur. Add yöntemini doğrudan çağırabilirsiniz ve öğenin zaten mevcut olup olmamasına bağlı olarak true veya false döndürür.
LukeH

1
Gereksiz İçerir çağrısını kaldırmak için yanıt düzenlenmelidir. Yukarıdaki örneğin çalışması için ihtiyacınız olan her şey: var collectionWithDup = new [] {"bir", "bir", "iki", "bir", "iki", "sıfır"}; var uniqueValues ​​= new HashSet <string> (collectionWithDup);
user3285954

14

Bunun iyi bir cevap olup olmadığından emin değilim, ancak ekleme sırasını koruyan benzersiz bir sete ihtiyaç duyduğumda, bir HashSet ve bir List ile yan yana uzlaştım. Bu durumda, sete her ekleme yaptığınızda aşağıdakileri yapın:

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

Öğeleri çıkarırken, her ikisinden de çıkardığınızdan emin olun. Bu nedenle, listeye başka hiçbir şeyin öğe eklemediğinden emin olduğunuz sürece, ekleme sıralı benzersiz bir setiniz olur!


10

Linq'i şu şekilde de kullanabilirsiniz:

using System.Linq;

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

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

8

HashSet kullanın, kontrol etmeye gerek yok .Contains (), sadece öğelerinizi listeye ekleyin ve kopyası varsa onu eklemeyecektir.

   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

Bu, sistem ad alanının bir parçası değildir ancak http://www.codeproject.com/KB/recipes/sets.aspx adresindeki Iesi.Collections'ı NHibernate ile kullanmıştır . Sıralı küme, sözlük kümesi vb. İle birlikte karma küme desteği vardır. NHibernate ile birlikte kullanıldığı için yaygın bir şekilde kullanılmıştır ve oldukça kararlıdır. Bu da .Net 3.5 gerektirmez


2

İşte HashSet.

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

Bu başlıktan benimsenmiştir: başlığından javascript - Bir dizideki benzersiz değerler

Ölçek:

using FluentAssertions;

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

Performans testi List, HashSetve SortedSet. 1 milyon yineleme:

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

Test kaynak kodu (özet)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.