Linq sélectionne les objets dans la liste où existe IN (A, B, C)

169

J'ai une liste de orders.
Je souhaite effectuer une sélection en ordersfonction d'un ensemble de statuts de commande.

Donc essentiellement 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
la source
Merci à tout ce qui a répondu si rapidement. Esp pour la solution lambda. Je n'ai encore rien fait avec les expressions lambda. Je suppose que je ferais un NOT contient en utilisant (o =>! (Statuses.Contains (o.OrderHeaderOrderStatusCode)))
MartinS

Réponses:

288

Vos codes de statut sont également une collection, alors utilisez Contains:

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

ou dans la syntaxe de requête:

var filteredOrders = from order in orders.Order
                     where allowedStatus.Contains(order.StatusCode)
                     select order;
Tim Schmelter
la source
1
Je dirais que utilisez HashSet au lieu de array pour allowedStatus car la méthode contient de HashSet est la plus rapide et il y aura des problèmes de performances avec le tableau s'il contient plus de 1000 éléments. var allowedStatus = new HashSet <chaîne> {"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;

la source
15

NB: il s'agit de LINQ to objects, je ne suis pas sûr à 100% si cela fonctionne en LINQ to entity, et je n'ai pas le temps de le vérifier pour le moment. En fait, il n'est pas trop difficile de le traduire en x dans [A, B, C] mais vous devez vérifier par vous-même.

Donc, au lieu de Contient en remplacement de ???? dans votre code, vous pouvez utiliser Any qui est plus 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;

C'est le contraire de ce que vous savez de SQL, c'est pourquoi ce n'est pas si évident.

Bien sûr, si vous préférez une syntaxe fluide, voici:

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

Ici, nous voyons à nouveau l'une des surprises LINQ (comme Joda-speech qui met select à la fin). Cependant, il est assez logique en ce sens qu'il vérifie si au moins un des éléments (c'est-à-dire n'importe lequel ) d'une liste (ensemble, collection) correspond à une seule valeur.

Alexandre Christov
la source
12

Essayez avec la Containsfonction;

Détermine si une séquence contient un élément spécifié.

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

Faites juste attention, .Contains()correspondra à toute sous-chaîne, y compris la chaîne que vous ne vous attendez pas. Pour par exemple. new[] { "A", "B", "AA" }.Contains("A")vous rendra A et AA dont vous pourriez ne pas vouloir. J'en ai été mordu.

.Any()ou .Exists()est un choix plus sûr

Balvinder Singh
la source
new [] {"B", "AA"} .Contains ("A") renverra faux, PAS vrai.
Jay Shah