user1527762
user1527762

Reputation: 957

Finding common elements within a list of objects

I have the following code

public class OrderDetails
{
    public int OrderId { get; set; }

    public int CustomerId { get; set; }

}

public List<int> GetCustomerIds()
{
    var orderDetails = new List<OrderDetails>
    {
        new OrderDetails {OrderId = 1001, CustomerId = 2001},
        new OrderDetails {OrderId = 1001, CustomerId = 2002},

        new OrderDetails {OrderId = 1002, CustomerId = 2003},
        new OrderDetails {OrderId = 1002, CustomerId = 2002},

        new OrderDetails {OrderId = 1003, CustomerId = 2003},
        new OrderDetails {OrderId = 1003, CustomerId = 2002},     
        //return list of common customerIds.           
    };
} 

I want to get a list of CustomerIds that are common across all orders. In the example above my output would be 2002. What is a clean way of achieving this?

Upvotes: 4

Views: 205

Answers (2)

Daniel Br&#252;ckner
Daniel Br&#252;ckner

Reputation: 59705

First find the total number of orders, then group the order details by customer and finally select the customers with the same number of orders as the total number of orders. This assumes no duplicate customer order pairs.

var numberOrders = orderDetails.Select(orderDetail => orderDetail.OrderId)
                               .Distinct()
                               .Count();

var result = orderDetails.GroupBy(orderDetail => orderDetail.CustomerId)
                         .Where(group => group.Count() == numberOrders)
                         .Select(group => group.Key)
                         .ToList();

Upvotes: 1

Jeroen Vannevel
Jeroen Vannevel

Reputation: 44438

This will accomplish what you want:

var result = orders.GroupBy(x => x.CustomerId)
                   .Where(y => y.Count() == orderDetails.GroupBy(z => z.OrderId)
                                                        .Count())
                   .FirstOrDefault()
                   .Key;

Output:

2002

We can read the purpose from the query in English:

  • Group your collection on the CustomerId
  • Gather how many different orders there are by grouping on OrderId and getting the Count()
  • Filter the collection to those customers which appear as often as there are orders
  • Select the first
  • Print the key (which is the CustomerId)

Important note: this will only take the first customer in case there are multiple with the same amount of orders, but changing this to take them all is trivial.

Upvotes: 6

Related Questions