Kolejność Linq według wartości logicznej

111

Mam zapytanie linq, które chcę uporządkować według f.bar, który jest łańcuchem, ale chcę też zamówić je najpierw według f.foo, które jest polem boolowskim. Jak zapytanie poniżej.

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

Chociaż to kompiluje, nie działa zgodnie z oczekiwaniami. Po prostu rozkazuje f.bar ignorując pole boolowskie.

Jestem głupi, wiem, ale co muszę zrobić, aby uzyskać takie zachowanie?

Dzięki

mat-mcloughlin
źródło

Odpowiedzi:

175

To powinno działać dobrze - powinno falsenajpierw uporządkować jednostki z wartością foo, a następnie te z rozszerzeniemtrue wartością foo.

To z pewnością działa w LINQ to Objects - którego dostawcy LINQ faktycznie używasz?

Oto przykład LINQ do obiektów, które czyni pracę:

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);
        }
    }

}
Jon Skeet
źródło
51
Epic Fail ... po prostu sobie sprawę, że z powodu błędów, które oznaczało f.foo zawsze był fałszywy .... tak zakłopotany
MAT-McLoughlin
5
Prawidłowo, false(0) znajduje się przed true(1) w rosnącej (domyślnej) kolejności sortowania.
silkfire
Jak pogrupować kolumnę Column1 według liczby prawdy w kolumnie 2?
Oracular Man
2
@OracularMan: Proponuję zadać nowe pytanie ze szczegółowym przykładem.
Jon Skeet,
1
@Sipo: Asdata.OrderBy(d => d.x).ThenBy(d => d.y)
Jon Skeet
119

Chciałem to zrobić i wygląda na to, że jest to coś bez ukrytego zamówienia. Zrobiłem następujące, aby być bardziej wyraźnym:

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

sortować coś od prawdziwego do fałszywego.

JonnyRaa
źródło
27
Bardziej mi się to podoba niż zabudowa. Głównie dlatego, że nawet jeśli istnieje domniemana kolejność prawda / fałsz, nie jest to tak naprawdę oczywiste dla nikogo, kto wcześniej tego nie zrobił. Więc ktoś, kto nie wie, jak patrzeć na kod w przyszłości, może pomyśleć, że sortuje on prawdę do fałszu, podczas gdy tak naprawdę sortuje fałsz do prawdy ... przynajmniej w tym rozwiązaniu kod sprawia, że ​​boleśnie oczywiste jest, w jaki sposób zamierzasz posortować.
Robert Noack
2
tak, podoba mi się to w kodzie! Jeśli musisz przejść do msdn lub stackoverflow, aby przeczytać dokumentację, aby zrozumieć kod, to moim zdaniem nie jest to świetny kod
JonnyRaa
2
Dla mnie pachnie magicznymi liczbami. Czy nie mylę się zakładając, że każdy programista powinien z natury bardzo dobrze wiedzieć, że wartość logiczna trueoznacza a single bit set to 1? Dla mnie prawda true > falsejest tak oczywista, jak to tylko możliwe.
Mels,
4
@Mels nie magiczne liczby. Jawne wartości używane tylko do sortowania i sortowania. Wartości mogą wynosić 42 i 69, chodzi o to, że czytelnik kodu wie, że jeden z nich jest mniejszy, dlatego będzie pierwszy. Czytelnik kodu prawdopodobnie nie wie, w jaki sposób OrderBy ustawi wartości logiczne - czy prawda będzie pierwsza, czy fałsz będzie pierwsza. true > falsenie jest powszechnie znana, podczas gdy 1 > 0jest.
Dan F
9
Należy zauważyć, że .OrderBy(e => e.SomeFlag == true)byłoby równoważne .OrderBy(e => e.SomeFlag)natomiast .OrderBy(e => e.SomeFlag ? 0 : 1)jest odpowiednikiem .OrderByDescending(e => e.SomeFlag). Pierwsze dwa oznaczają fałsz przed fałszem, pozostałe dwa przed fałszem.
EriF89
0

Spróbuj wykonać następujący kod, jeśli otrzymujesz list orderby true.

db.member.where(x=>x.id==memberId).OrderBy(x=>!x.IsPrimary?1:0).ToList();
Muhammad Armaghan
źródło
0

W celu dokładniejszego określenia używanej kolejności.

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; 
    }
}
Wouter
źródło