Linq seleziona gli oggetti nell'elenco dove esiste IN (A, B, C)


169

Ho un elenco di orders.
Voglio selezionare in ordersbase a una serie di stati dell'ordine.

Quindi essenzialmente 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;

Grazie a tutto ciò che ha risposto così rapidamente. Esp per la soluzione lambda. Non ho ancora fatto nulla con le espressioni lambda. Presumo che farei un NOT contiene utilizzando (o =>! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))
MartinS

Risposte:


288

I tuoi codici di stato sono anche una raccolta, quindi usa Contains:

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

o nella sintassi della query:

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

1
Direi che usa HashSet invece dell'array per consentitiStatus perché il metodo HashSet contiene è il più veloce e ci saranno problemi di prestazioni con l'array se contiene più di 1000 elementi. var consentitoStatus = new HashSet <stringa> {"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;

15

NB: questo è LINQ per gli oggetti, non sono sicuro al 100% se funziona in LINQ per le entità e non ho tempo per verificarlo in questo momento. In effetti non è troppo difficile tradurlo in x in [A, B, C] ma devi controllare tu stesso.

Quindi, invece di Contiene in sostituzione del ???? nel tuo codice puoi usare Any che è più 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;

È l'opposto di quello che sai da SQL, per questo non è così ovvio.

Naturalmente, se preferisci la sintassi fluida qui è:

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

Qui vediamo di nuovo una delle sorprese di LINQ (come il discorso di Joda che mette fine alla selezione). Tuttavia è abbastanza logico in questo senso che controlla se almeno uno degli elementi (ovvero qualsiasi ) in un elenco (set, raccolta) corrisponde a un singolo valore.


12

Prova con la Containsfunzione;

Determina se una sequenza contiene un elemento specificato.

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

-3

.Contains()Fai solo attenzione, corrisponderà a qualsiasi sottostringa inclusa la stringa che non ti aspetti. Per es. new[] { "A", "B", "AA" }.Contains("A")ti restituirà sia A che AA che potresti non desiderare. Sono stato morso da esso.

.Any()o .Exists()è una scelta più sicura


new [] {"B", "AA"} .Contains ("A") restituirà false, NON true.
Jay Shah,
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.