Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ: Searching a collection within a collection for a single object

Tags:

c#

linq

I am looking for a nice simple LINQ query that can get an item that is in a collection of a collection. Consider the following models...

class Customer
{
   List<Order> Orders;
   int ID;
}

class Order
{
   int ID;
}

Lets say I have a list of type customer...

List<Customer> Customers;

What I want is a single Order based on the ID of the Order (this is my known input data). I also can assume that an Order is unique to a customer (so there will only be one Order with the ID I am looking for across all customers)

Is there a nice LINQ query I can use to get the Order I am looking for?

I know I can easily do this over a single list of Orders, but this is the set up I have to work with. I do not want to be querying for more data, ff I already have enough in memory to get what I need.

I could do this with a semi-messy for loop. Maybe I should just do this? Maybe I am trying to simplify the code too much?

like image 574
musefan Avatar asked Dec 19 '11 16:12

musefan


1 Answers

Oops, misread the question:

var matchingOrders = from customer in customers
                     from order in customer.Orders
                     where order.ID == orderID
                     select order;

var order = matchingOrders.Single();

As in an earlier version of this answer, note that this will fail if there are no such matches or more than one. You may also want to look at SingleOrDefault, First, and FirstOrDefault.

This code can also be written without query expressions using SelectMany:

var order = customers.SelectMany(customer => customer.Orders)
                     .Single(order => order.ID == orderID);

Note that you don't need to use Where and then Single - there's a Single overload taking a predicate (and likewise for FirstOrDefault etc). Whether you use the query expression form or not is up to you - I usually use query expressions rather than SelectMany, but in this case you don't need the customer, so you can use the simple overload of SelectMany.

like image 166
Jon Skeet Avatar answered Nov 15 '22 11:11

Jon Skeet