Ein Nebenknoten: Wenn eine "normale" HashSet<string>(Groß- und Kleinschreibung beachten ) erstellt wird, ist es unmöglich, eine containseffiziente Methode zu erstellen . Dies liegt daran, dass die Hashes der Elemente erstellt werden, wenn sie dem hinzugefügt werden HashSet. Und intern containsüberprüft die Methode die Hashes, um effizient zu sein. Es ist nicht möglich, eine vorhandene Hash-Form (Groß- und Kleinschreibung beachten) (effizient) in "Groß- und Kleinschreibung beachten" umzuwandeln.
Julian
Antworten:
121
Sie können das HashSetmit einem benutzerdefinierten Vergleicher erstellen:
HashSet<string> hs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
hs.Add("Hello");
Console.WriteLine(hs.Contains("HeLLo"));
+1 Weil du Ordinalstatt verwendest InvariantCulture. In den .NET-Richtlinien wird empfohlen, diese InvariantCulturein den meisten Fällen nicht zu verwenden (siehe: msdn.microsoft.com/en-us/library/ms973919.aspx ).
Steven
1
CurrentCultureIgnoreCase ist normalerweise die bessere Wahl.
Hans Passant
1
mdsdn sagt: Verwenden Sie StringComparison.Ordinal oder OrdinalIgnoreCase für Vergleiche als sichere Standardeinstellung für kulturunabhängigen String-Abgleich.
Amit
2
Ich glaube, dass CurrentCultureIgnoreCase den "Türkei-Test" nicht bestehen wird. "LIST" und "list" stimmen nicht überein, wenn die aktuelle Kultur die Türkei ist, da der Kleinbuchstabe "I" in dieser Kultur nicht "i" ist, sondern "ı" ohne Punkt. Wenn Sie also "LIST" == "list" erwarten, werden Sie enttäuscht sein, dass wenn die aktuelle Kultur Truthahn ist, dies falsch zurückgibt. Wenn die Zeichenfolgen, die Sie vergleichen, keine Zeichenfolgen in der Sprache des Benutzers sind, dh wenn es sich um Zeichenfolgen handelt, die nichts mit der Sprache des Benutzers zu tun haben, verwenden Sie InvariantCultureIgnoreCase
AaronLS
1
Kann nicht bearbeitet werden, stimmt jedoch, dass OrdinalIgnoreCase normalerweise InvariantCultureIgnoreCase vorgezogen wird. Ich wollte nur darauf hinweisen, warum CurrentCultureIgnoreCase wahrscheinlich nicht anwendbar ist (hängt jedoch davon ab, ob es sich um eine Zeichenfolge handelt, die für die Sprache des Benutzers relevant ist oder nicht).
AaronLS
10
Sie müssen es mit dem Recht erstellen IEqualityComparer:
HashSet<string> hashset = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
Dies ist hier nicht erforderlich, wie andere Antworten gezeigt haben. In anderen Fällen, in denen Sie keine Zeichenfolge verwenden, können Sie eine implementieren IEqualityComparer<T>und anschließend eine .ContainsÜberladung verwenden. Hier ist ein Beispiel mit einer Zeichenfolge (andere Antworten haben gezeigt, dass es bereits einen Zeichenfolgenvergleicher gibt, den Sie verwenden können, der Ihren Anforderungen entspricht). Viele Methoden in der Umgebung IEnumerable<T>weisen Überladungen auf, die solche Vergleicher akzeptieren. Daher ist es gut zu lernen, wie man sie implementiert.
HashSet<string>
(Groß- und Kleinschreibung beachten ) erstellt wird, ist es unmöglich, einecontains
effiziente Methode zu erstellen . Dies liegt daran, dass die Hashes der Elemente erstellt werden, wenn sie dem hinzugefügt werdenHashSet
. Und interncontains
überprüft die Methode die Hashes, um effizient zu sein. Es ist nicht möglich, eine vorhandene Hash-Form (Groß- und Kleinschreibung beachten) (effizient) in "Groß- und Kleinschreibung beachten" umzuwandeln.Antworten:
Sie können das
HashSet
mit einem benutzerdefinierten Vergleicher erstellen:HashSet<string> hs = new HashSet<string>(StringComparer.OrdinalIgnoreCase); hs.Add("Hello"); Console.WriteLine(hs.Contains("HeLLo"));
quelle
Ordinal
statt verwendestInvariantCulture
. In den .NET-Richtlinien wird empfohlen, dieseInvariantCulture
in den meisten Fällen nicht zu verwenden (siehe: msdn.microsoft.com/en-us/library/ms973919.aspx ).Sie müssen es mit dem Recht erstellen
IEqualityComparer
:HashSet<string> hashset = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
quelle
Dies ist hier nicht erforderlich, wie andere Antworten gezeigt haben. In anderen Fällen, in denen Sie keine Zeichenfolge verwenden, können Sie eine implementieren
IEqualityComparer<T>
und anschließend eine.Contains
Überladung verwenden. Hier ist ein Beispiel mit einer Zeichenfolge (andere Antworten haben gezeigt, dass es bereits einen Zeichenfolgenvergleicher gibt, den Sie verwenden können, der Ihren Anforderungen entspricht). Viele Methoden in der UmgebungIEnumerable<T>
weisen Überladungen auf, die solche Vergleicher akzeptieren. Daher ist es gut zu lernen, wie man sie implementiert.class CustomStringComparer : IEqualityComparer<string> { public bool Equals(string x, string y) { return x.Equals(y, StringComparison.InvariantCultureIgnoreCase); } public int GetHashCode(string obj) { return obj.GetHashCode(); } }
Und dann benutze es
bool contains = hash.Contains("foo", new CustomStringComparer());
quelle
Sie sollten den Konstruktor verwenden , mit dem
IEqualityComparer
Sie den gewünschten Konstruktor angeben können .HashSet<String> hashSet = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);
Das StringComparer- Objekt bietet einige häufig verwendete Vergleiche als statische Eigenschaften.
quelle