Effiziente Liste eindeutiger Zeichenfolgen C #


86

Was ist der effizienteste Weg, um eine Liste von Zeichenfolgen zu speichern, bei der Duplikate ignoriert werden? Ich dachte, ein Wörterbuch könnte am besten Zeichenfolgen einfügen, indem Sie dict [str] = false schreiben. und Auflisten durch die Schlüssel als Liste. Ist das eine gute Lösung?

Antworten:


111

Wenn Sie .NET 3.5 verwenden, sollte das HashSet für Sie funktionieren.

Die HashSet <(Of <(T>)>) - Klasse bietet hochleistungsfähige Set-Operationen. Ein Satz ist eine Sammlung, die keine doppelten Elemente enthält und deren Elemente in keiner bestimmten Reihenfolge vorliegen.


5
Aber a HashSetwird die Reihenfolge der Artikel verlieren. Eine Funktion, die a Listbietet.
Aggsol

4
Zusätzlich: Es gibt auch SortedSet <T>, ein bequem sortiertes HashSet.
WhoIsRich

Beachten Sie auch, dass auf HashSet nicht über einen Index zugegriffen werden kann, sondern nur über einen Enumerator im Gegensatz zu einer Liste.
Andrew

23

Sie können schauen, um so etwas zu tun

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
Sie benötigen die Contains-Prüfung nicht mit einem HashSet. Sie können die Add-Methode einfach direkt aufrufen und sie gibt true oder false zurück, je nachdem, ob das Element bereits vorhanden ist oder nicht.
LukeH

1
Die Antwort sollte bearbeitet werden, um den Aufruf zu redundanten Contains zu entfernen. Dies ist alles, was Sie für das obige Beispiel benötigen: var collectionWithDup = new [] {"eins", "eins", "zwei", "eins", "zwei", "null"}; var uniqueValues ​​= new HashSet <string> (collectionWithDup);
user3285954

14

Ich bin mir nicht sicher, ob dies eine gute Antwort ist, aber angesichts der Notwendigkeit eines eindeutigen Satzes, der die Einfügereihenfolge beibehält, habe ich einen Kompromiss zwischen einem HashSet und einer Liste nebeneinander eingegangen. Führen Sie in diesem Fall Folgendes aus, wenn Sie dem Set hinzufügen:

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

Stellen Sie beim Entfernen von Elementen sicher, dass Sie beide entfernen. Solange Sie also sicher sein können, dass nichts anderes Elemente zur Liste hinzugefügt hat, haben Sie ein einzigartiges Set mit Einfügungsreihenfolge!


10

Sie können Linq auch wie folgt verwenden:

using System.Linq;

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

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

8

Verwenden Sie HashSet, ohne dass Sie .Contains () überprüfen müssen. Fügen Sie einfach Ihre Elemente zur Liste hinzu, und wenn es doppelt vorhanden ist, wird es nicht hinzugefügt.

   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

Dies ist nicht Teil des System-Namespace, hat jedoch die Iesi.Collections von http://www.codeproject.com/KB/recipes/sets.aspx mit NHibernate verwendet. Es unterstützt Hash-Sets zusammen mit sortierten Sets, Wörterbuchsets usw. Da es mit NHibernate verwendet wurde, wurde es ausgiebig und sehr stabil verwendet. Dies erfordert auch nicht .Net 3.5


2

Hier ist eine andere Lösung ohne die HashSet.

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

Es wurde von diesem Thread übernommen: Javascript - Eindeutige Werte in einem Array

Prüfung:

using FluentAssertions;

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

Performance - Test für List, HashSetund SortedSet. 1 Million Iterationen:

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

Quellcode testen (Kern)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.