Linq select objects in list where exists IN (A,B,C)

C#LinqListLinq to-ObjectsExists

C# Problem Overview


I have a list of orders.
I want to select orders based on a set of order statuses.

So essentially 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;

C# Solutions


Solution 1 - C#

Your status-codes are also a collection, so use Contains:

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

or in query syntax:

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

Solution 2 - C#

var statuses = new[] { "A", "B", "C" };

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

Solution 3 - C#

NB: this is LINQ to objects, I am not 100% sure if it works in LINQ to entities, and have no time to check it right now. In fact it isn't too difficult to translate it to x in [A, B, C] but you have to check for yourself.

So, instead of Contains as a replacement of the ???? in your code you can use Any which is more 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;

It's the opposite to what you know from SQL this is why it is not so obvious.

Of course, if you prefer fluent syntax here it is:

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

Here we again see one of the LINQ surprises (like Joda-speech which puts select at the end). However it is quite logical in this sense that it checks if at least one of the items (that is any) in a list (set, collection) matches a single value.

Solution 4 - C#

Try with Contains function;

> Determines whether a sequence contains a specified element.

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

Solution 5 - C#

Just be careful, .Contains() will match any substring including the string that you do not expect. For eg. new[] { "A", "B", "AA" }.Contains("A") will return you both A and AA which you might not want. I have been bitten by it.

.Any() or .Exists() is safer choice

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMartinSView Question on Stackoverflow
Solution 1 - C#Tim SchmelterView Answer on Stackoverflow
Solution 2 - C#user439931View Answer on Stackoverflow
Solution 3 - C#Alexander ChristovView Answer on Stackoverflow
Solution 4 - C#Soner GönülView Answer on Stackoverflow
Solution 5 - C#Balvinder SinghView Answer on Stackoverflow