Ordine di Linq per booleano


111

Ho una query linq che voglio ordinare per f.bar, che è una stringa, ma voglio anche ordinarla prima per f.foo, che è un campo booleano. Come la query di seguito.

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

Sebbene venga compilato, non funziona come previsto. Ordina solo per f.bar ignorando il campo booleano.

Sono stupido, lo so, ma cosa devo fare per ottenere questo comportamento?

Grazie

Risposte:


175

Dovrebbe funzionare bene: dovrebbe ordinare prima le entità con un falsevalore foo, poi quelle con un truevalore foo.

Funziona sicuramente in LINQ to Objects: quale provider LINQ stai effettivamente utilizzando?

Ecco un LINQ to Objects esempio che fa il lavoro:

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
Fallimento epico ... ho appena capito che era dovuto a un bug che significava che f.foo era sempre falso ... quindi imbarazzato
mat-mcloughlin

5
Corretto, false(0) viene prima di true(1) in ordine crescente (predefinito).
silkfire

Come faccio a raggruppare la Colonna1 per numero di vero nella Colonna 2?
Oracular Man

2
@OracularMan: ti suggerisco di fare una nuova domanda con un esempio dettagliato.
Jon Skeet

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

119

Volevo solo farlo e sembra qualcosa senza un ordine implicito. Ho fatto quanto segue per essere più esplicito:

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

per ordinare qualcosa di vero in falso.


27
Mi piace più del modo integrato. Principalmente perché anche se c'è un ordine implicito per vero / falso, non è davvero ovvio per chi non l'ha fatto prima. Quindi qualcuno che non sa guardare il codice in futuro potrebbe pensare che ordina da vero a falso, quando in realtà ordina da falso a vero ... almeno con questa soluzione, il codice rende dolorosamente ovvio il modo in cui intendi ordinare.
Robert Noack

2
sì, mi piace in codice! Se devi andare su msdn o stackoverflow per leggere la documentazione per capire il codice, secondo me non è un ottimo codice
JonnyRaa

2
Odora di numeri magici per me. Mi sbaglio nel presumere che ogni programmatore dovrebbe intrinsecamente sapere molto bene che un booleano truesignifica a single bit set to 1? Per me, la verità true > falseè quanto più ovvia può essere.
Mels

4
@Mels non numeri magici. Valori espliciti utilizzati solo per l'ordinamento e l'ordinamento. I valori potrebbero essere 42 e 69, il punto è che il lettore del codice sa che uno di loro è più piccolo, quindi sarà il primo. Il lettore del codice probabilmente non sa in che modo un OrderBy inserirà i bool - sarà vero per primo o falso per primo. true > falsenon è universalmente noto, mentre lo 1 > 0è.
Dan F

9
Nota che .OrderBy(e => e.SomeFlag == true)sarebbe equivalente a .OrderBy(e => e.SomeFlag)mentre .OrderBy(e => e.SomeFlag ? 0 : 1)è l'equivalente di .OrderByDescending(e => e.SomeFlag). I primi due ordinano falso prima di vero, gli altri due ordinano vero prima di falso.
EriF89

0

Per favore prova a seguire il codice se ottieni list orderby true.

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

0

Per essere più espliciti sull'ordine utilizzato.

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; 
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.