Wie verwende ich die HashSet <string> .Contains () -Methode im Modus ohne Berücksichtigung der Groß- und Kleinschreibung?

70

Wie verwende HashSet<string>.Contains()ich die Methode im Modus ohne Berücksichtigung der Groß- und Kleinschreibung?

Tasawer Khan
quelle
5
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"));
João Angelo
quelle
15
+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);
Kobi
quelle
6

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.

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());
Anthony Pegram
quelle
5

Sie sollten den Konstruktor verwenden , mit dem IEqualityComparerSie 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.

Thibault Falise
quelle