Linq wybiera obiekty z listy, jeśli istnieje IN (A, B, C)

169

Mam listę orders.
Chcę wybrać ordersna podstawie zestawu statusów zamówień.

Więc zasadniczo 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
źródło
Dzięki wszystkim, którzy tak szybko odpowiedzieli. Esp dla rozwiązania lambda. Nie zrobiłem jeszcze nic z wyrażeniami lambda. Zakładam, że zrobiłbym NIE zawiera using (o =>! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))
MartinS

Odpowiedzi:

288

Twoje kody statusu również są zbiorem, więc użyj Contains:

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

lub w składni zapytania:

var filteredOrders = from order in orders.Order
                     where allowedStatus.Contains(order.StatusCode)
                     select order;
Tim Schmelter
źródło
1
Powiedziałbym, że użyj HashSet zamiast array dla allowedStatus, ponieważ metoda HashSet zawiera najszybszą metodę i wystąpią problemy z wydajnością z tablicą, jeśli zawiera ona więcej niż 1000 elementów. 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;

źródło
15

Uwaga: to jest LINQ to objects, nie jestem w 100% pewien, czy działa w LINQ to entity, i nie mam czasu, aby to sprawdzić teraz. W rzeczywistości nie jest zbyt trudne, aby przetłumaczyć to na x w [A, B, C], ale musisz sam to sprawdzić.

Więc zamiast Zawiera jako zamiennik ???? w swoim kodzie możesz użyć dowolnego, który jest bardziej 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;

Jest to przeciwieństwo tego, co znasz z SQL, dlatego nie jest to takie oczywiste.

Oczywiście, jeśli wolisz płynną składnię, jest to:

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

Tutaj znowu widzimy jedną z niespodzianek LINQ (jak mowa Jody, która umieszcza wybór na końcu). Jednak w tym sensie jest całkiem logiczne, że sprawdza, czy co najmniej jeden z elementów (to znaczy którekolwiek ) na liście (zestaw, kolekcja) pasuje do pojedynczej wartości.

Aleksandra Christowa
źródło
12

Spróbuj z Containsfunkcją;

Określa, czy sekwencja zawiera określony element.

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

Po prostu bądź ostrożny, .Contains()dopasuje każdy podciąg, w tym łańcuch, którego nie oczekujesz. Np. new[] { "A", "B", "AA" }.Contains("A")zwróci ci zarówno A, jak i AA, których możesz nie chcieć. Zostałem przez to ugryziony.

.Any()lub .Exists()jest bezpieczniejszym wyborem

Balvinder Singh
źródło
new [] {"B", "AA"} .Contains ("A") zwróci fałsz, NIE prawda.
Jay Shah