Linq memilih objek dalam daftar di mana ada IN (A, B, C)

169

Saya punya daftar orders.
Saya ingin memilih ordersberdasarkan serangkaian status pesanan.

Jadi intinya select orders where order.StatusCode in ("A", "B", "C")

// Filter the orders based on the order status
var filteredOrders = from order in orders.Order
                     where order.StatusCode.????????("A", "B", "C")
                     select order;
MartinS
sumber
Terima kasih untuk semua yang menjawab begitu cepat. Terutama untuk solusi lambda. Saya belum melakukan apa pun dengan ekspresi lambda. Saya berasumsi saya akan membuat TIDAK mengandung menggunakan (o =>! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))
MartinS

Jawaban:

288

Kode status Anda juga merupakan koleksi, jadi gunakan Contains:

var allowedStatus = new[]{ "A", "B", "C" };
var filteredOrders = orders.Order.Where(o => allowedStatus.Contains(o.StatusCode));

atau dalam sintaks kueri:

var filteredOrders = from order in orders.Order
                     where allowedStatus.Contains(order.StatusCode)
                     select order;
Tim Schmelter
sumber
1
Saya akan mengatakan bahwa menggunakan HashSet bukan array untuk allowStatus karena metode HashSet berisi lebih cepat dan akan ada masalah kinerja dengan array jika mengandung lebih dari 1000 item. var allowedStatus = HashSet baru <string> {"A", "B", "C"};
Jay Shah
15
var statuses = new[] { "A", "B", "C" };

var filteredOrders = from order in orders.Order
                             where statuses.Contains(order.StatusCode)
                             select order;

sumber
15

NB: ini adalah LINQ untuk objek, saya tidak 100% yakin apakah itu bekerja di LINQ ke entitas, dan tidak punya waktu untuk memeriksanya sekarang. Sebenarnya tidak terlalu sulit untuk menerjemahkannya menjadi x dalam [A, B, C] tetapi Anda harus memeriksanya sendiri.

Jadi, alih-alih Berisi sebagai pengganti ???? dalam kode Anda, Anda dapat menggunakan Apa saja yang lebih LINQ-uish:

// Filter the orders based on the order status
var filteredOrders = from order in orders.Order
                     where new[] { "A", "B", "C" }.Any(s => s == order.StatusCode)
                     select order;

Ini kebalikan dari apa yang Anda ketahui dari SQL. Itulah mengapa tidak begitu jelas.

Tentu saja, jika Anda lebih memilih sintaks yang lancar di sini adalah:

var filteredOrders = orders.Order.Where(order => new[] {"A", "B", "C"}.Any(s => s == order.StatusCode));

Di sini kita kembali melihat salah satu kejutan LINQ (seperti Joda-speech yang menempatkan pilih di akhir). Namun cukup logis dalam hal ini memeriksa apakah setidaknya salah satu item (yaitu ada ) dalam daftar (set, koleksi) cocok dengan nilai tunggal.

Alexander Christov
sumber
12

Coba dengan Containsfungsi;

Menentukan apakah urutan berisi elemen yang ditentukan.

var allowedStatus = new[]{ "A", "B", "C" };
var filteredOrders = orders.Order.Where(o => allowedStatus.Contains(o.StatusCode));
Soner Gönül
sumber
-3

Hanya hati-hati, .Contains()akan cocok dengan semua substring termasuk string yang tidak Anda harapkan. Untuk misalnya. new[] { "A", "B", "AA" }.Contains("A")akan mengembalikan A dan AA yang mungkin tidak Anda inginkan. Saya telah digigit olehnya.

.Any()atau .Exists()pilihan yang lebih aman

Balvinder Singh
sumber
baru [] {"B", "AA"} .Berisi ("A") akan mengembalikan false, BUKAN benar.
Jay Shah