hunB
hunB

Reputation: 331

Group a list by a list of object

I have a list of list of object that I try to group by one of the list of object.

I tried the following code but it is not grouping anything

I have a list of type myObj like [obj1[],obj2[],obj3[],obj4[]]

I tried

 myObj.GroupBy(
            a => new { a.obj1},
            a => new { a.obj2, a.obj3, a.obj4})
            .Select(x => new myObj 
            {
                obj1= x.Key.obj1,
                obj2= x.SelectMany(l => l.obj2).Distinct().ToList(),
                obj3= x.SelectMany(list => list.obj3).Distinct().ToList(),
                obj4= x.SelectMany(list => list.obj4).Distinct().ToList(),
            }
            )
            .ToList();

but it outputs the same as myObj

e.g.

myObj = [
 {[a1],[a2,b2,c2],[e2],[f4,g4]},
 {[a1],[d2,e2],[e3],[f4]},
 {[a2,a1],[d2,e2],[e3],[f4]},
 {[a2],[d2,e2],[e3],[f4,g4]},
 {[a2],[a2,d2,e2],[e3,f3],[f4]},
 ]

I want the output :

myGroupedObj = [
{[a1],[a2,b2,c2,d2,e2],[e2,e3],[f4,g4]},
{[a2,a1],[d2,e2],[e3],[f4]},
{[a2],[a2,d2,e2],[e3,f3],[f4,g4]},
]

Upvotes: 0

Views: 99

Answers (2)

Edward
Edward

Reputation: 8596

You need a custom comparer, see link @mjwills posted.

Custom comparer example:

public class ListComparer : IEqualityComparer<List<object>>
{
    public bool Equals(List<object> a, List<object> b)
    {
        if (a.Count != b.Count)
            return false;
        for (int i = 0; i < a.Count; i++)
            if (a[i] != b[i]) 
                return false;
        return true;
    }

    public int GetHashCode(List<object> list)
    {
        var hash = 0;
        foreach (var item in list)
        {
            hash = hash ^ item.GetHashCode();
        }
        return hash;
    }
}

Add this custom comparer to the GroupBy and your original code now works as you expected:

myObjs
    .GroupBy(a => a.obj1, new ListComparer())
    .Select(x => new myObj
    {
    obj1 = x.Key,
    obj2 = x.SelectMany(l => l.obj2).Distinct().ToList(),
    obj3 = x.SelectMany(list => list.obj3).Distinct().ToList(),
    obj4 = x.SelectMany(list => list.obj4).Distinct().ToList(),
    })
    .ToList();

Upvotes: 2

gofal3
gofal3

Reputation: 1238

In any case the problem is your KeySelector. the key you select is "a => new { a.obj1 }". So for every item you create a new instance of the key. Since there is no equality comparer overload the only comparision is reference equal. The key-selector has to return instances, where the GroupBy method can perform "==" operation and realy gets the same value.

I cannot reproduce your sample, so i cannot verify if this is the only issue, but in any case your KeySelector should be: a => a.obj1

and of course you have to change the first assignment in your Select-Statement to obj1= x.Key,

Upvotes: 0

Related Questions