Commande Linq par booléen

111

J'ai une requête linq que je veux commander par f.bar, qui est une chaîne, mais je veux aussi la commander par f.foo, qui est un champ booléen, d'abord. Comme la requête ci-dessous.

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

Bien que cela compile, cela ne fonctionne pas comme prévu. Il commande simplement par f.bar en ignorant le champ booléen.

Je suis stupide, je sais, mais que dois-je faire pour obtenir ce comportement?

Merci

mat-mcloughlin
la source

Réponses:

175

Cela devrait fonctionner correctement - il devrait ordonner les entités avec une falsevaleur foo en premier, puis celles avec une truevaleur foo.

Cela fonctionne certainement dans LINQ to Objects - quel fournisseur LINQ utilisez-vous réellement?

Voici un exemple LINQ à des objets qui ne travail:

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
la source
51
Échec épique ... vient de réaliser que c'était dû à un bug qui signifiait que f.foo était toujours faux ... tellement embarrassé
mat-mcloughlin
5
Correct, false(0) vient avant true(1) dans l'ordre de tri croissant (par défaut).
silkfire
Comment regrouper la colonne 1 par nombre de vrai dans la colonne 2?
Oracular Man
2
@OracularMan: Je vous suggère de poser une nouvelle question avec un exemple détaillé.
Jon Skeet
1
@Sipo: Asdata.OrderBy(d => d.x).ThenBy(d => d.y)
Jon Skeet
119

Je voulais juste faire cela et cela semble être quelque chose sans ordre implicite. J'ai fait ce qui suit pour être plus explicite:

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

pour trier quelque chose de vrai à faux.

JonnyRaa
la source
27
J'aime en quelque sorte cela plus que la manière intégrée. Principalement parce que même s'il y a un ordre implicite pour vrai / faux, ce n'est pas vraiment évident pour quiconque ne l'a pas fait auparavant. Donc, quelqu'un qui ne sait pas regarder le code à l'avenir pourrait penser qu'il trie du vrai au faux, alors qu'en réalité il trie le faux au vrai ... au moins avec cette solution, le code rend douloureusement évident de quelle manière vous avez l'intention de trier.
Robert Noack
2
ouais j'aime ça dans le code! Si vous devez aller sur msdn ou stackoverflow pour lire la documentation pour comprendre le code, ce n'est pas un excellent code à mon avis
JonnyRaa
2
Ça sent les nombres magiques pour moi. Ai-je tort de supposer que chaque programmeur doit intrinsèquement savoir très bien que truesignifie un booléen a single bit set to 1? Pour moi, la vérité sur true > falseest à peu près aussi évidente que possible.
Mels
4
@Mels pas des nombres magiques. Valeurs explicites utilisées pour le tri et le tri uniquement. Les valeurs pourraient être 42 et 69, le fait est que le lecteur du code sait que l'un d'entre eux est plus petit, donc sera le premier. Le lecteur du code ne sait probablement pas de quelle manière un OrderBy placera les booléens - sera vrai en premier, ou faux sera en premier. true > falsen'est pas universellement connue, alors qu'elle l' 1 > 0est.
Dan F
9
Notez que .OrderBy(e => e.SomeFlag == true)cela équivaut à .OrderBy(e => e.SomeFlag)alors que .OrderBy(e => e.SomeFlag ? 0 : 1)est l'équivalent de .OrderByDescending(e => e.SomeFlag). Les deux premiers trient faux avant vrai, les deux autres trient vrai avant faux.
EriF89
0

Veuillez essayer le code suivant si vous obtenez la commande de la liste par true.

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

Afin d'être plus explicite sur la commande utilisée.

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
la source