Linq seleciona objetos na lista onde existe IN (A, B, C)

169

Eu tenho uma lista de orders.
Desejo selecionar com ordersbase em um conjunto de status de pedidos.

Então essencialmente 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
fonte
Obrigado a todos que responderam tão rapidamente. Esp para a solução lambda. Ainda não fiz nada com expressões lambda. Eu suponho que eu faria um contém não usando (o => (statuses.Contains (o.OrderHeaderOrderStatusCode))!)
Martins

Respostas:

288

Seus códigos de status também são uma coleção, então use Contains:

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

ou na sintaxe da consulta:

var filteredOrders = from order in orders.Order
                     where allowedStatus.Contains(order.StatusCode)
                     select order;
Tim Schmelter
fonte
1
Eu diria que use HashSet em vez de matriz para allowedStatus porque o método HashSet contém é o mais rápido e haverá problemas de desempenho com a matriz se ela contiver mais de 1000 itens. var allowedStatus = new HashSet <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;

fonte
15

Nota: este é o LINQ to objects, não tenho 100% de certeza se ele funciona no LINQ to entidades e não tenho tempo para verificá-lo agora. De fato, não é muito difícil traduzi-lo para x em [A, B, C] mas você deve verificar por si mesmo.

Então, em vez de Contém como uma substituição do ???? No seu código, você pode usar Qualquer um que seja mais 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;

É o oposto do que você sabe do SQL, é por isso que não é tão óbvio.

Obviamente, se você preferir uma sintaxe fluente, aqui está:

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

Aqui, novamente, vemos uma das surpresas do LINQ (como Joda-speech, que coloca select no final). No entanto, é bastante lógico nesse sentido que ele verifique se pelo menos um dos itens (que é algum ) em uma lista (conjunto, coleção) corresponde a um único valor.

Alexander Christov
fonte
12

Tente com Containsfunção;

Determina se uma sequência contém um elemento especificado.

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

Apenas tome cuidado, .Contains()ele corresponderá a qualquer substring, incluindo a string que você não espera. Por exemplo. new[] { "A", "B", "AA" }.Contains("A")retornará os dois A e AA que você pode não querer. Eu fui mordido por ele.

.Any()ou .Exists()é uma escolha mais segura

Balvinder Singh
fonte
new [] {"B", "AA"}. Contém ("A") retornará false, NOT true.
Jay Shah