demo demo - 3 months ago 8
C# Question

Separate collection on 2 different NEW collections

I have collection of elements and one additional small collection as filter.

I need to separate it on 2 new collections by some filter. In my case it is first collection that contains some elements and another that doesn't.

There aren't items that doesn't exists out of that 2 new collections.

I did it like :

var collection1= baseCollection.Where(r => filterCollection.Contains(r.Property)).ToList();
var collection2= baseCollection.Where(r => !filterCollection.Contains(r.Property)).ToList();


But is there another, I hope more elegant way, to separate collection?
For me it looks like "I repeat myself", use almost the same code 2 times.

Answer
  1. If your type of the collection overrides Equals and GetHashCode you can use Except:

    var collection1 = baseCollection.Where(r => filterCollection.Contains(r.Property));
    var collection2 = baseCollection.Except(collection1);
    
  2. Using Except with a given IEqualityComparer (Check also first comment for guidlines):

    public class Comparer : IEqualityComparer<YourClass>
    {
        public bool Equals(YourClass x, YourClass y)
        {
            // Your implementation
        }
    
        public int GetHashCode(YourClass obj)
        {
            // Your implementation
        }
    }
    
    var collection1 = baseCollection.Where(r => filterCollection.Contains(r.Property));
    var collection2 = baseCollection.Except(collection1, new Comparer());
    
  3. You can also use GroupBy:

    var result baseCollection.GroupBy(r => filterCollection.Contains(r.Property))
                             .ToDictionary(key => key.Key, value => value.ToList());
    
    var collection1 = result[true];
    var collection2 = result[false];
    
  4. Otherwise another way will just to use a loop:

    List<YourType> collection1 = new List<YourType>();
    List<YourType> collection2 = new List<YourType>();
    foreach(var item in baseCollection)
    {
        if(filterCollection.Contains(item.Property))
        {
            collection1.Add(item);
        }
        else
        {
            collection2.Add(item);
        }
    }