2013-04-24 8 views
9

Gibt es trotzdem eine LINQ2SQL Abfrage zu tun, etwas zu tun, ähnlich wie diese:Groß- und Kleinschreibung Gruppe auf mehrere Spalten

var result = source.GroupBy(a => new { a.Column1, a.Column2 }); 

oder

var result = from s in source 
      group s by new { s.Column1, s.Column2 } into c 
      select new { Column1 = c.Key.Column1, Column2 = c.Key.Column2 }; 

aber mit zu ignorieren, den Fall des Inhalts der gruppierten Spalten ?

+0

Dies funktioniert nicht? 'a => {Column1 = a.Column1.ToLower(), Column2 = a.Column2.ToLower()}' –

Antwort

18

Sie können StringComparer.InvariantCultureIgnoreCase an die Erweiterungsmethode GroupBy übergeben.

var result = source.GroupBy(a => new { a.Column1, a.Column2 }, 
       StringComparer.InvariantCultureIgnoreCase); 

Oder können Sie ToUpperInvariant auf jedem Feld verwenden, wie von Hamlet Hakobyan auf Kommentar vorgeschlagen. Ich empfehle ToUpperInvariant oder ToUpper anstatt ToLower oder ToLowerInvariant, weil es für programmatischen Vergleich Zweck optimiert ist.

+6

Ein 'StringComparer' kann Instanzen von anonymen Typen, nur Strings, nicht vergleichen. Eine neue Vergleichsimplementierung wird benötigt (siehe die Antwort von Bill B) –

+0

@DiegoMijelshon, wenn "Column1" und "Column2" vom Typ "string" sind, dann "GroupBy (a => a.Column1 + a.Column2, StringComparer.InvariantCultureIgnoreCase)" sollte funktionieren – fubo

5

Ich konnte nicht NaveenBhat-Lösung zu arbeiten, einen Compiler-Fehler bekommen:

The type arguments for method 'System.Linq.Enumerable.GroupBy(System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IEqualityComparer)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

, damit es funktioniert, fand ich es am einfachsten und klarsten eine neue Klasse zu definieren meine Schlüsselspalten zu speichern (groupkey) , dann eine separate Klasse, die IEqualityComparer (KeyComparer) implementiert. Ich kann dann

var result= source.GroupBy(r => new GroupKey(r), new KeyComparer()); 

Die KeyComparer Klasse nennt die Saiten mit dem InvariantCultureIgnoreCase comparer nicht zu vergleichen, so einem dicken Lob für den Hinweis mich in der richtigen Richtung NaveenBhat.

Vereinfachte Versionen meiner Klassen:

private class GroupKey 
{ 
    public string Column1{ get; set; } 
    public string Column2{ get; set; } 

    public GroupKey(SourceObject r) { 
     this.Column1 = r.Column1; 
     this.Column2 = r.Column2; 
    } 
} 

private class KeyComparer: IEqualityComparer<GroupKey> 
{ 

    bool IEqualityComparer<GroupKey>.Equals(GroupKey x, GroupKey y) 
    { 
     if (!x.Column1.Equals(y.Column1,StringComparer.InvariantCultureIgnoreCase) return false; 
     if (!x.Column2.Equals(y.Column2,StringComparer.InvariantCultureIgnoreCase) return false; 
     return true; 
     //my actual code is more complex than this, more columns to compare 
     //and handles null strings, but you get the idea. 
    } 

    int IEqualityComparer<GroupKey>.GetHashCode(GroupKey obj) 
    { 
     return 0.GetHashCode() ; // forces calling Equals 
     //Note, it would be more efficient to do something like 
     //string hcode = Column1.ToLower() + Column2.ToLower(); 
     //return hcode.GetHashCode(); 
     //but my object is more complex than this simplified example 

    } 
} 
+0

Sind Sie sicher, dass Sie nicht einfach 'StringComparison.InvariantCultureIgnoreCase' (was eine Enum ist) anstelle von' StringComparer.InvariantCultureIgnoreCase' (was ist eine Klasse)? –

+0

Sie sind richtig, @dav_i, das ist die Quelle des "Ich kann nicht von 'System.StringComparison' ..." Fehler konvertieren, den ich erhalten habe. Aber selbst wenn ich diesen Fehler nicht mache, wurde ein anderer Kompilierungsfehler ausgelöst. Ich habe meine Antwort aktualisiert, um das aufgetretene Problem und die Gründe für diese Lösung widerzuspiegeln. Vielen Dank! –

1

Ich hatte das gleiche Problem, das von den Werten von DataRow-Objekte aus einer Tabelle Gruppierung, aber ich nur .ToString() auf der DataRow-Objekt verwendet hinter dem Compiler zu erhalten Ausgabe, z

MyTable.AsEnumerable().GroupBy(
    dataRow => dataRow["Value"].ToString(), 
    StringComparer.InvariantCultureIgnoreCase) 

statt

MyTable.AsEnumerable().GroupBy(
    dataRow => dataRow["Value"], 
    StringComparer.InvariantCultureIgnoreCase) 
Verwandte Themen