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

У меня есть список 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;

person MartinS    schedule 10.01.2013    source источник
comment
Спасибо всем, что ответили так быстро. Esp для лямбда-решения. Я еще ничего не делал с лямбда-выражениями. Я предполагаю, что я бы НЕ использовал using (o = ›! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))   -  person MartinS    schedule 10.01.2013


Ответы (4)


Ваши коды состояния также являются коллекцией, поэтому используйте 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;
person Tim Schmelter    schedule 10.01.2013
comment
Я бы сказал, что используйте HashSet вместо массива для allowedStatus, потому что метод HashSet contains самый быстрый, и возникнут проблемы с производительностью с массивом, если он содержит более 1000 элементов. var allowedStatus = new HashSet ‹string› {A, B, C}; - person Jay Shah; 09.11.2018
comment
@JayShah: поздний ответ: да, в целом вы правы, если у вас тысячи предметов, возможно, лучше вообще использовать HashSet<T>. Но это не всегда хорошая идея: вам нужна другая коллекция, поэтому больше памяти, если вы уже передаете массив или список. Вам нужно заполнить это HashSet<T>, так что больше циклов процессора. Возможно, вы все равно не сможете использовать тысячи элементов, если это не Linq-To-Objects, а Linq-To-Entities (Contains переводится в предложение sql-IN, которое имеет ограничения). - person Tim Schmelter; 31.05.2021

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

Таким образом, вместо Содержит вместо ???? в вашем коде вы можете использовать Любой, который больше похож на LINQ:

// 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 в конец). Однако в этом смысле вполне логично, что он проверяет, соответствует ли хотя бы один из элементов (то есть любой) в списке (наборе, коллекции) единственному значению.

person Alexander Christov    schedule 26.07.2015

Попробуйте использовать функцию Contains;

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

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

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

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

person Balvinder Singh    schedule 19.06.2018
comment
new [] {B, AA} .Contains (A) вернет false, а НЕ истину. - person Jay Shah; 09.11.2018