Linq выбрать объекты в списке, где существует IN (A, B, C)

169

У меня есть список orders.
Я хочу выбрать ordersна основе набора статусов заказа.

Так по сути 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
источник
Спасибо за все, что ответили так быстро. Esp для лямбда-решения. Я еще ничего не сделал с лямбда-выражениями. Я предполагаю, что я сделал бы НЕ содержит использование (o =>! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))
MartinS

Ответы:

288

Ваши коды состояния также являются коллекцией, поэтому используйте Contains:

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

или в синтаксисе запроса:

var filteredOrders = from order in orders.Order
                     where allowedStatus.Contains(order.StatusCode)
                     select order;
Тим Шмельтер
источник
1
Я бы сказал, что используйте HashSet вместо массива для allowStatus, потому что метод hashSet содержит самый быстрый метод и возникнут проблемы с производительностью массива, если он содержит более 1000 элементов. var allowStatus = new HashSet <string> {"A", "B", "C"};
Джей Шах
15
var statuses = new[] { "A", "B", "C" };

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

источник
15

NB: это LINQ для объектов, я не уверен на 100%, работает ли он в LINQ для объектов, и у меня нет времени проверять это прямо сейчас. На самом деле это не так уж сложно перевести на x в [A, B, C], но вы должны проверить это сами.

Итак, вместо Содержит в качестве замены ???? в вашем коде вы можете использовать Any, более 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;

Это противоположно тому, что вы знаете из SQL, поэтому это не так очевидно.

Конечно, если вы предпочитаете свободный синтаксис, вот он:

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

Здесь мы снова видим один из сюрпризов LINQ (например, Joda-speech, который ставит select в конце). Однако в этом смысле вполне логично, что он проверяет, соответствует ли хотя бы один из элементов (то есть любой ) в списке (множество, коллекция) одному значению.

Александр Христов
источник
12

Попробуй с Containsфункцией;

Определяет, содержит ли последовательность указанный элемент.

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

Только будьте осторожны, .Contains()подойдет любая подстрока, включая строку, которую вы не ожидаете. Например, new[] { "A", "B", "AA" }.Contains("A")вернет вам оба A и AA, которые вы можете не захотеть. Я был укушен этим.

.Any()или .Exists()более безопасный выбор

Балвиндер Сингх
источник
new [] {"B", "AA"} .Contains ("A") вернет false, а не true.
Джей Шах,