Порядок в Linq по логическому

111

У меня есть запрос linq, который я хочу упорядочить по f.bar, который является строкой, но я также хочу сначала упорядочить его по f.foo, которое является логическим полем. Как и запрос ниже.

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

Хотя это компилируется, он работает не так, как ожидалось. Он просто приказывает f.bar игнорировать логическое поле.

Я дурак, я знаю, но что мне нужно сделать, чтобы добиться такого поведения?

Спасибо

Мэт-Маклафлин
источник

Ответы:

175

Это должно работать нормально - falseсначала нужно упорядочить объекты со значением foo, а затем - со trueзначением foo.

Это определенно работает в LINQ to Objects - какой поставщик LINQ вы на самом деле используете?

Вот пример LINQ to Objects, который действительно работает:

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
Эпический провал ... только что понял, что это из-за ошибки, из-за которой f.foo всегда был ложным .... так смущен
mat-mcloughlin
5
Правильно, false(0) стоит перед true(1) в порядке сортировки по возрастанию (по умолчанию).
silkfire
Как сгруппировать Column1 по количеству истинных значений в столбце 2?
Oracular Man
2
@OracularMan: Предлагаю вам задать новый вопрос с подробным примером.
Джон Скит
1
@Sipo: Asdata.OrderBy(d => d.x).ThenBy(d => d.y)
Джон Скит
119

Просто хотел это сделать, и это похоже на что-то без неявного упорядочивания. Для большей ясности я сделал следующее:

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

отсортировать что-то истинное и ложное.

JonnyRaa
источник
27
Мне это нравится больше, чем встроенное. В основном потому, что даже если есть подразумеваемое упорядочивание по истине / ложному, это не совсем очевидно для тех, кто не делал этого раньше. Так что тот, кто не разбирается в коде в будущем, может подумать, что он сортируется от истинного к ложному, хотя на самом деле он сортирует от ложного к истинному ... по крайней мере, с этим решением, код делает до боли очевидным, каким образом вы собираетесь сортировать.
Роберт Ноак
2
да, мне нравится это в коде! Если вам нужно перейти на msdn или stackoverflow, чтобы прочитать документацию, чтобы понять код, то, на мой взгляд, это не
лучший
2
Для меня пахнет волшебными числами. Я ошибаюсь, полагая, что каждый программист должен очень хорошо знать, что trueозначает логическое значение a single bit set to 1? Для меня истина true > falseнастолько очевидна, насколько это возможно.
Mels
4
@Mels не магические числа. Явные значения используются только для сортировки и сортировки. Значения могут быть 42 и 69, дело в том, что читатель кода знает, что одно из них меньше, поэтому будет первым. Читатель кода, вероятно, не знает, в какую сторону OrderBy поместит булевые значения - первым будет true или первым будет false. true > falseне общеизвестно, тогда как 1 > 0есть.
Дэн Ф
9
Обратите внимание, что это .OrderBy(e => e.SomeFlag == true)было бы эквивалентно .OrderBy(e => e.SomeFlag)тогда, когда .OrderBy(e => e.SomeFlag ? 0 : 1)это эквивалент .OrderByDescending(e => e.SomeFlag). Первые два сортируют ложь перед истиной, два других сортируют истину перед ложью.
EriF89
0

Пожалуйста, попробуйте следующий код, если вы получили список заказов по истине.

db.member.where(x=>x.id==memberId).OrderBy(x=>!x.IsPrimary?1:0).ToList();
Мухаммад Армаган
источник
0

Для более точного определения используемого порядка.

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; 
    }
}
Воутер
источник