Linq-Reihenfolge nach Booleschen Werten


111

Ich habe eine Linq-Abfrage, die ich nach f.bar, einer Zeichenfolge, bestellen möchte, aber ich möchte sie auch zuerst nach f.foo, einem booleschen Feld, bestellen. Wie die Abfrage unten.

(from f in foo
orderby f.foo, f.bar
select f)

Obwohl dies kompiliert wird, funktioniert es nicht wie erwartet. Es wird nur von f.bar bestellt, wobei das boolesche Feld ignoriert wird.

Ich bin dumm, ich weiß, aber was muss ich tun, um dieses Verhalten zu bekommen?

Vielen Dank

Antworten:


175

Das sollte gut funktionieren - es sollte zuerst die Entitäten mit einem falsefoo-Wert und dann die mit einem truefoo-Wert ordnen.

Das funktioniert sicherlich in LINQ to Objects - welchen LINQ-Anbieter verwenden Sie tatsächlich?

Hier ist ein Beispiel für LINQ to Objects, das funktioniert :

using System;
using System.Linq;

public static class Test
{
    public static void Main()
    {
        var data = new[]
        {
            new { x = false, y = "hello" },
            new { x = true, y = "abc" },
            new { x = false, y = "def" },
            new { x = true, y = "world" }
        };

        var query = from d in data
                    orderby d.x, d.y
                    select d;

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

}

51
Epic fail ... habe gerade gemerkt, dass es an einem Fehler lag, der bedeutete, dass f.foo immer falsch war ... so peinlich
mat-mcloughlin

5
Richtig, false(0) steht vor true(1) in aufsteigender (Standard-) Sortierreihenfolge.
Seidenfeuer

Wie gruppiere ich die Spalte1 nach der Anzahl der Wahren in Spalte 2?
Oracular Man

2
@OracularMan: Ich schlage vor, Sie stellen eine neue Frage mit einem detaillierten Beispiel.
Jon Skeet

1
@Sipo: Asdata.OrderBy(d => d.x).ThenBy(d => d.y)
Jon Skeet

119

Ich wollte das nur tun und es scheint etwas ohne implizite Reihenfolge zu sein. Ich habe Folgendes getan, um genauer zu sein:

Something.OrderBy(e=>e.SomeFlag ? 0 : 1) 

etwas wahr bis falsch sortieren.


27
Ich mag das mehr als die eingebaute Art und Weise. Hauptsächlich, weil selbst wenn es eine implizite Reihenfolge für wahr / falsch gibt, dies für niemanden wirklich offensichtlich ist, der dies noch nicht getan hat. Jemand, der nicht weiß, wie er in Zukunft Code betrachtet, könnte denken, dass er von wahr nach falsch sortiert, wenn er wirklich falsch zu wahr sortiert. Zumindest bei dieser Lösung macht der Code schmerzlich deutlich, in welche Richtung Sie sortieren möchten.
Robert Noack

2
Ja, das gefällt mir im Code! Wenn Sie auf msdn oder stackoverflow gehen müssen, um die Dokumentation zu lesen, um Code zu verstehen, dann ist es meiner Meinung nach kein großartiger Code
JonnyRaa

2
Riecht für mich nach magischen Zahlen. Bin ich falsch in der Annahme, dass jeder Programmierer von Natur aus sehr gut wissen sollte, dass ein Boolescher Wert truebedeutet a single bit set to 1? Für mich ist die Wahrheit true > falseso offensichtlich wie möglich.
Mels

4
@Mels keine magischen Zahlen. Explizite Werte, die nur zum Sortieren und Sortieren verwendet werden. Die Werte könnten 42 und 69 sein, der Punkt ist, dass der Leser des Codes weiß, dass einer von ihnen kleiner ist, daher wird zuerst. Der Leser des Codes weiß wahrscheinlich nicht, in welche Richtung ein OrderBy die Bools setzt - wird wahr zuerst sein oder wird falsch zuerst sein. true > falseist nicht allgemein bekannt, wohingegen 1 > 0.
Dan F

9
Beachten Sie, dass .OrderBy(e => e.SomeFlag == true)dies äquivalent zu ist , .OrderBy(e => e.SomeFlag)während .OrderBy(e => e.SomeFlag ? 0 : 1)das Äquivalent von ist .OrderByDescending(e => e.SomeFlag). Die ersten beiden Sorten sind falsch vor wahr, die anderen beiden Arten sind wahr vor falsch.
EriF89

0

Bitte versuchen Sie den folgenden Code, wenn Sie die Liste orderby true erhalten.

db.member.where(x=>x.id==memberId).OrderBy(x=>!x.IsPrimary?1:0).ToList();

0

Um die verwendete Reihenfolge genauer zu beschreiben.

Something.OrderBy(e => e.SomeFlag, new BooleanComparer());

public class BooleanComparer : IComparer<bool>
{
    public int Compare(bool x, bool y)
    {
        int p = x ? 1 : 0;
        int q = y ? 1 : 0;
        return p - q; 
    }
}
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.