LINQ Unterschiedlicher Operator, Groß- / Kleinschreibung ignorieren?


95

Anhand des folgenden einfachen Beispiels:

    List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" };

    CaseInsensitiveComparer ignoreCaseComparer = new CaseInsensitiveComparer();

    var distinctList = list.Distinct(ignoreCaseComparer as IEqualityComparer<string>).ToList();

Es scheint, dass der CaseInsensitiveComparer nicht verwendet wird, um einen Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung durchzuführen.

Mit anderen Worten, differentList enthält die gleiche Anzahl von Elementen wie list . Stattdessen würde ich zum Beispiel erwarten, dass "Drei" und "Drei" als gleich angesehen werden.

Vermisse ich etwas oder ist dies ein Problem mit dem Distinct-Operator?

Antworten:


227

StringComparer macht was du brauchst:

List<string> list = new List<string>() {
    "One", "Two", "Three", "three", "Four", "Five" };

var distinctList = list.Distinct(
    StringComparer.CurrentCultureIgnoreCase).ToList();

(oder invariant / ordinal / etc abhängig von den Daten, die Sie vergleichen)


5

[Siehe Marc Gravells Antwort, wenn Sie den präzisesten Ansatz wünschen]

Nach einigen Nachforschungen und guten Rückmeldungen von Bradley Grainger habe ich den folgenden IEqualityComparer implementiert. Es unterstützt eine Distinct () -Anweisung, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird (übergeben Sie einfach eine Instanz davon an den Distinct-Operator):

class IgnoreCaseComparer : IEqualityComparer<string>
{
    public CaseInsensitiveComparer myComparer;

    public IgnoreCaseComparer()
    {
        myComparer = CaseInsensitiveComparer.DefaultInvariant;
    }

    public IgnoreCaseComparer(CultureInfo myCulture)
    {
        myComparer = new CaseInsensitiveComparer(myCulture);
    }

    #region IEqualityComparer<string> Members

    public bool Equals(string x, string y)
    {
        if (myComparer.Compare(x, y) == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetHashCode(string obj)
    {
        return obj.ToLower().GetHashCode();
    }

    #endregion
}

6
Das brauchst du einfach nicht. Siehe meine Antwort.
— Marc Gravell

2
Ja, Ihre Antwort ist gerade eingetroffen, als ich auf "Antwort posten" geklickt habe.
— Ash

Ich erinnere mich, dass sie mit <20 Sekunden Abstand voneinander waren. Trotzdem ist die Implementierung von IEqualityComparer <T> immer noch eine nützliche Übung, schon allein, um zu verstehen, wie es funktioniert ...
— Marc Gravell

Nochmals vielen Dank, ich werde diese Antwort dann leben lassen, es sei denn, jemand widerspricht stark.
— Ash

Dieses Beispiel schlägt bei der Initialisierung für die tr-TR-Kultur fehl, wenn die aktuelle Kultur en-US ist, da GetHashCode unterschiedliche Werte für I (U + 0049) und ı (U + 0131) meldet, während Equals sie als gleich betrachtet.
— Bradley Grainger

1

 ## Distinct Operator( Ignoring Case) ##
  string[] countries = {"USA","usa","INDIA","UK","UK" };

  var result = countries.Distinct(StringComparer.OrdinalIgnoreCase);

  foreach (var v in result) 
  { 
  Console.WriteLine(v);
  }

OutPut wird sein

   USA 
   INDIA
   UK

3
Bitte vermeiden Sie es, Code-Schnipsel ohne Erklärung zu veröffentlichen. Bearbeiten Sie Ihre Antwort und fügen Sie einen Text hinzu. Vielen Dank.
— Clijsters

0

Hier ist eine viel einfachere Version.

List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" };

var z = (from x in list select new { item = x.ToLower()}).Distinct();

z.Dump();
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.