Daftar efisien dari string unik C #


86

Apa cara paling efisien untuk menyimpan daftar string yang mengabaikan duplikat? Saya berpikir kamus mungkin paling baik memasukkan string dengan menulis dict [str] = false; dan menghitung melalui tombol sebagai daftar. Apakah itu solusi yang bagus?

Jawaban:


111

Jika Anda menggunakan .NET 3.5, HashSet akan bekerja untuk Anda.

Kelas HashSet <(Of <(T>)>) menyediakan operasi set kinerja tinggi. Himpunan adalah kumpulan yang tidak berisi elemen duplikat, dan yang elemennya tidak berada dalam urutan tertentu.


6
Tapi HashSetakan kehilangan urutan item. Sebuah fitur a Listmenyediakan.
aggsol

5
Tambahan: Ada juga SortedSet <T> yang merupakan HashSet terurut yang nyaman.
WhoIsRich

Perhatikan juga bahwa HashSet tidak dapat diakses melalui indeks, hanya melalui enumerator sebagai lawan dari Daftar.
Andrew

23

Anda dapat melakukan sesuatu seperti ini

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
Anda tidak perlu cek Berisi dengan HashSet. Anda bisa langsung memanggil metode Add dan itu akan mengembalikan true atau false tergantung pada apakah item tersebut sudah ada atau tidak.
LukeH

1
Jawaban harus diedit untuk menghapus panggilan ke Berisi yang berlebihan. Ini semua yang Anda perlukan agar contoh di atas berfungsi: var collectionWithDup = new [] {"one", "one", "two", "one", "two", "zero"}; var uniqueValues ​​= HashSet baru <string> (collectionWithDup);
pengguna3285954

14

Saya tidak yakin apakah ini dianggap sebagai jawaban yang baik, tetapi ketika dihadapkan dengan kebutuhan akan rangkaian unik yang mempertahankan urutan penyisipan, saya berkompromi dengan HashSet dan Daftar secara berdampingan. Dalam kasus ini, setiap kali Anda menambahkan ke set, lakukan hal berikut:

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

Saat menghapus item, pastikan untuk menghapusnya dari keduanya. Jadi, selama Anda dapat yakin bahwa tidak ada item lain yang ditambahkan ke daftar, Anda akan memiliki set unik berurutan penyisipan!


10

Anda juga bisa menggunakan Linq seperti pada:

using System.Linq;

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

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

8

Gunakan HashSet, tidak perlu memeriksa .Contains (), cukup tambahkan item Anda dalam daftar dan jika duplikatnya tidak akan menambahkannya.

   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

Ini bukan bagian dari namespace sistem tetapi telah menggunakan Iesi.Collections dari http://www.codeproject.com/KB/recipes/sets.aspx dengan NHibernate. Ini memiliki dukungan untuk set hash bersama dengan set yang diurutkan, set kamus, dan sebagainya. Karena telah digunakan dengan NHibernate, ini telah digunakan secara ekstensif dan sangat stabil. Ini juga tidak membutuhkan .Net 3.5


2

Berikut adalah solusi lain tanpa menggunakan HashSet.

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

Itu diadopsi dari utas ini: javascript - Nilai unik dalam larik

Uji:

using FluentAssertions;

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

Uji kinerja untuk List, HashSetdan SortedSet. 1 juta iterasi:

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

Uji kode sumber (intisari)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.