Urutan Linq berdasarkan boolean


111

Saya memiliki kueri linq yang ingin saya pesan berdasarkan f.bar, yang merupakan string, tetapi saya juga ingin mengurutkan berdasarkan f.foo, yang merupakan bidang boolean, terlebih dahulu. Seperti query di bawah ini.

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

Meskipun kompilasi ini tidak berfungsi seperti yang diharapkan. Itu hanya memerintahkan dengan f.bar mengabaikan bidang boolean.

Saya memang gila, saya tahu, tapi apa yang harus saya lakukan untuk mendapatkan perilaku ini?

Terima kasih

Jawaban:


175

Itu seharusnya berfungsi dengan baik - itu harus memesan entitas dengan falsenilai foo terlebih dahulu, kemudian yang memiliki truenilai foo.

Itu pasti berfungsi di LINQ ke Objek - penyedia LINQ mana yang sebenarnya Anda gunakan?

Berikut adalah LINQ untuk Objects contoh yang tidak bekerja:

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 gagal ... baru sadar itu karena bug yang berarti f.foo selalu salah .... sangat memalukan
mat-mcloughlin

5
Benar, false(0) muncul sebelum true(1) dalam urutan pengurutan menaik (default).
Silkfire

Bagaimana cara mengelompokkan Kolom1 dengan bilangan benar di Kolom 2?
Oracular Man

2
@OracularMan: Saya sarankan Anda mengajukan pertanyaan baru dengan contoh terperinci.
Jon Skeet

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

119

Hanya ingin melakukan ini dan sepertinya sesuatu tanpa urutan implisit. Saya melakukan hal berikut untuk lebih eksplisit:

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

untuk mengurutkan sesuatu yang benar menjadi salah.


27
Saya menyukai ini lebih dari yang dibangun dengan cara. Terutama karena meskipun ada urutan tersirat untuk benar / salah, itu tidak terlalu jelas bagi siapa pun yang belum pernah melakukannya sebelumnya. Jadi seseorang yang tidak tahu melihat kode di masa depan dapat berpikir itu diurutkan dari benar ke salah, padahal sebenarnya itu mengurutkan salah menjadi benar ... setidaknya dengan solusi ini, kode membuatnya sangat jelas ke arah mana Anda ingin mengurutkan.
Robert Noack

2
ya saya suka itu dalam kode! Jika Anda harus pergi ke msdn atau stackoverflow untuk membaca dokumentasi untuk memahami kode maka itu bukan kode yang bagus menurut saya
JonnyRaa

2
Baunya seperti angka ajaib bagiku. Am aku salah dalam asumsi bahwa setiap programmer harus inheren tahu betul bahwa boolean trueberarti a single bit set to 1? Bagi saya, kebenaran true > falseadalah sejelas mungkin.
Mels

4
@Els bukan angka ajaib. Nilai eksplisit digunakan untuk pengurutan dan pengurutan saja. Nilainya bisa 42 dan 69, intinya adalah pembaca kode mengetahui bahwa salah satunya lebih kecil, oleh karena itu akan menjadi yang pertama. Pembaca kode mungkin tidak tahu ke arah mana OrderBy akan menempatkan bools - true menjadi yang pertama, atau akan false menjadi yang pertama. true > falsetidak diketahui secara universal, padahal 1 > 0ada.
Dan F

9
Perhatikan bahwa .OrderBy(e => e.SomeFlag == true)akan setara dengan .OrderBy(e => e.SomeFlag)sedangkan .OrderBy(e => e.SomeFlag ? 0 : 1)adalah setara dengan .OrderByDescending(e => e.SomeFlag). Dua yang pertama mengurutkan salah sebelum benar, dua lainnya mengurutkan benar sebelum salah.
EriF89

0

Silakan coba kode berikut jika Anda mendapatkan daftar orderby benar.

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

0

Agar lebih eksplisit tentang pesanan yang digunakan.

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; 
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.