93 Stimmen

aufsteigend/absteigend in LINQ - kann man die Reihenfolge per Parameter ändern?

Ich habe eine Methode, der der Parameter "bool sortAscending" übergeben wird. Nun möchte ich LINQ verwenden, um eine sortierte Liste in Abhängigkeit von diesem Parameter zu erstellen. Ich habe dann dies:

var ascendingQuery = from data in dataList
                      orderby data.Property ascending
                      select data;

var descendingQuery = from data in dataList
                      orderby data.Property descending
                      select data;

Wie Sie sehen können, unterscheiden sich die beiden Abfragen nur in "aufsteigend" bzw. "absteigend". Ich würde gerne beide Abfragen zusammenführen, weiß aber nicht, wie. Hat jemand eine Antwort?

0 Stimmen

Sie möchten also eine Abfrage, die sowohl aufsteigend als auch absteigend, je nach bool sortAsvending Wert tun kann? Ist das korrekt.

134voto

Jon Skeet Punkte 1325502

Sie können leicht Ihre eigene Erweiterungsmethode für IEnumerable oder IQueryable erstellen:

public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource,TKey>
    (this IEnumerable<TSource> source,
     Func<TSource, TKey> keySelector,
     bool descending)
{
    return descending ? source.OrderByDescending(keySelector)
                      : source.OrderBy(keySelector);
}

public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey>
    (this IQueryable<TSource> source,
     Expression<Func<TSource, TKey>> keySelector,
     bool descending)
{
    return descending ? source.OrderByDescending(keySelector)
                      : source.OrderBy(keySelector);
}

Ja, Sie verlieren hier die Möglichkeit, einen Abfrageausdruck zu verwenden - aber ehrlich gesagt glaube ich nicht, dass Sie in diesem Fall überhaupt von einem Abfrageausdruck profitieren. Abfrageausdrücke sind großartig für komplexe Dinge, aber wenn Sie nur eine einzige Operation tun, ist es einfacher, nur diese eine Operation zu setzen:

var query = dataList.OrderByWithDirection(x => x.Property, direction);

4 Stimmen

Danke für die Korrektur meiner Dummheit, Marc :) (Das ist das Problem, wenn man kurz vor dem Mittagessen postet...)

11 Stimmen

Dieser Beitrag wurde von zwei Prominenten von SO.com beantwortet und bearbeitet

0 Stimmen

Sollte nicht eine der OrderByWithDirections aufsteigend zurückgegeben werden?

48voto

Marc Gravell Punkte 970173

In Bezug auf die Art und Weise, wie dies umgesetzt wird, ändert dies die Methode - von OrderBy/ThenBy zu OrderByDescending/ThenByDescending. Sie können die Sortierung jedoch separat auf die Hauptabfrage anwenden...

var qry = from .... // or just dataList.AsEnumerable()/AsQueryable()

if(sortAscending) {
    qry = qry.OrderBy(x=>x.Property);
} else {
    qry = qry.OrderByDescending(x=>x.Property);
}

Nützt das was? Sie können den gesamten "Auftrag" dynamisch erstellen, aber das ist aufwendiger...

Ein weiterer Trick (vor allem für LINQ-to-Objects geeignet) ist die Verwendung eines Multiplikators von -1/1. Dies ist nur für numerische Daten wirklich nützlich, aber es ist ein frecher Weg, um das gleiche Ergebnis zu erreichen.

1 Stimmen

Ich wollte gerade genau das Gleiche schreiben, dann ist mein VS eingefroren :(

1 Stimmen

Die Verwendung eines Multiplikators schlägt auch bei einem Rückgabewert von int.MinValue fehl.

0 Stimmen

Warum verwenden Sie die orderBy-Methode, anstatt das orderby-Schlüsselwort in einer linq-Abfrage zu verwenden?

8voto

sports Punkte 7375

Wie wäre es mit einer Sortierung nach der gewünschten Eigenschaft,

   blah = blah.OrderByDescending(x => x.Property);

Und dann etwas tun wie

  if (!descending)
  {
       blah = blah.Reverse()
  }
  else
  {
      // Already sorted desc ;)
  }

Ist es Reverse() zu langsam?

0 Stimmen

Wahrscheinlich nicht der optimalste, aber sicherlich ein sehr cleverer Ansatz

0 Stimmen

@DiegoPenha humm aber wenn es Linq zu Entitäten vor der Materialisierung von Daten sollte das gleiche sein, nicht wahr? Ich meine, es wird eine entsprechende Sql-Abfrage erzeugt. Sind Sie einverstanden?

0 Stimmen

@DiegoPenha Vergessen Sie es, linq to entities unterstützt die Funktion .Reverse() nicht

5voto

ehh Punkte 3232

Zusätzlich zu der schönen Lösung von @Jon Skeet brauchte ich auch ThenBy und ThenByDescending, also füge ich sie basierend auf seiner Lösung hinzu:

    public static IOrderedEnumerable<TSource> ThenByWithDirection<TSource, TKey>(
         this IOrderedEnumerable<TSource> source, 
         Func<TSource, TKey> keySelector,  
         bool descending)
    {
        return descending ? 
               source.ThenByDescending(keySelector) :
               source.ThenBy(keySelector);
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X