Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# and LINQ- group objects based on their IDs and then find common values in them

Tags:

c#

linq

I have a object collection like in the following.

  List<Product> productList=new List<Product>();

Structure of the class Product is like in the following.

   public class Product
   {
       public  int Id;
       public Product(int id)
       {
          Id=id;

       }

       public List<SomeOtherList> t;
  }

The class Product contains some other list

    public class SomeOtherList 
    {
        private int value;

        public  SomeOtherList(int val)
        {
            value=val;

       }


   }
        Product prodOne=new Product(1);
        List<SomeOtherList> temp_1=new List<SomeOtherList>();
        temp_1.Add(new SomeOtherList(10));
       temp_1.Add(new SomeOtherList(20));
       temp_1.Add(new SomeOtherList(30));
       prodOne.t=temp_1;

       Product prodTwo=new Product(2);
       List<SomeOtherList> temp_2=new List<SomeOtherList>();
       temp_2.Add(new SomeOtherList(100));
       temp_2.Add(new SomeOtherList(40));
       temp_2.Add(new SomeOtherList(30));
       prodTwo.t=temp_2;


       Product prodThree=new Product(1);
       List<SomeOtherList> temp_3=new List<SomeOtherList>();
       temp_3.Add(new SomeOtherList(10));
       temp_3.Add(new SomeOtherList(20));

       prodThree.t=temp_3;



      productList.Add(prodOne);
      productList.Add(prodTwo);
      productList.Add(prodThree);

I want to get "SomeOtherList" objects common to all the Products. For example, for Product Id 1, I should get SomeOtherList object 20 as the common One.

I have written the following LINQ query to achieve this.

   List<Product> t=productList
                          .GroupBy(p => p.Id)
                          .Where(g => g.Count() == productList.Count)
                          .Select(x => x.First())
                          .ToList();

But it does not give me what I want . Can someone point what is wrong with that query ?

like image 425
nidarshani fernando Avatar asked Jan 22 '26 07:01

nidarshani fernando


1 Answers

What you want is the intersection between your SomeOtherList when the product is some specific value (i.e. 1).

So you need to first select the each Product which has the correct Id and then join their SomeOtherList together and group by the value.

To do this we need to flattern the each SomeOtherList for a Product, which we can do with SelectMany

Projects each element of a sequence to an IEnumerable and flattens the resulting sequences into one sequence.


Single Id

If we are only intrested in a single Id then we can do the following

var common1 = productList
    .Where(product => product.Id == 1)
    .SelectMany(product => product.t)
    .GroupBy(groupValue => groupValue.value)
    .Where(groupValue => groupValue.Count() > 1)
    .Select(values => values.First());

This will:

  1. Filter the products based on Id being equal to 1
  2. Flattern each products SomeOtherList into one IEnumerable
  3. Group each element based on SomeOtherList.value
  4. Filter out any groups which only have 1 entry, as we only want those that are common

All Id's

If, however, we would like to get the list of all duplicates for each key then we can do the same as for a Single Id but have a first step where we group based on the Id.

var common = productList
    .GroupBy(groupId => groupId.Id)
    .Select(groupId => groupId.SelectMany(product => product.t)
        .GroupBy(groupValue => groupValue.value)
        .Where(groupValue => groupValue.Count() > 1)
        .Select(values => values.First().value));
like image 110
Joey Ciechanowicz Avatar answered Jan 23 '26 21:01

Joey Ciechanowicz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!