简体   繁体   English

如何按元素列表分组?

[英]How can I group by a list of elements?

I run into this issue again and again: how can I group a list of objects by a containing list of other objects? 我一次又一次地遇到这个问题:如何通过包含其他对象列表来对对象列表进行分组?

I have a list of objects of type A and each of these objects has an property (lets call it ListProp ) which is a list also. 我有一个类型A的对象列表,每个对象都有一个属性(让我们称之为ListProp ),这也是一个列表。 ListProp has elements of the type B . ListProp具有类型B元素。 There are multiple elements of type A with identically B -objects in ListProp , but the ListProp property reference differs from element to element. ListProp有多个类型为A且具有相同B对象的元素,但ListProp属性引用因元素而异。 How can I group these A -objects the fastest way, where the B -objects in ListProp are identically? 如何以最快的方式对这些A对象进行分组,其中ListProp中的B对象是相同的?

Sample code: 示例代码:

class Program
{
    static void Main(string[] args)
    {
        var exampleList = new List<A>
        {
            // Should be in first group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in first group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in second group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in third group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 0 }}
            }}
        };

        // Doesn't work because the reference of ListProp is always different
        var groupedExampleList = exampleList.GroupBy(x => x.ListProp);
    }
}

class C
{
    public int Number { get; set; }
    public override bool Equals(object o)
    {
        if (o is C)
            return Number.Equals(((C)o).Number);
        else
            return false;
    }
}

class B
{
    public C Prop { get; set; }
}

class A
{
    public IList<B> ListProp { get; set; }
}

You can implement IEqualityComparer<List<B>> and use it in the other GroupBy overload. 您可以实现IEqualityComparer<List<B>>并在其他GroupBy重载中使用它。

public class ListOfBEqualityComparer : IEqualityComparer<List<B>>
{
    public bool Equals(List<B> x, List<B> y)
    {
        // you can also implement IEqualityComparer<B> and use the overload
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<B> obj)
    {
        //implementation of List<T> may not work for your situation
        return obj.GetHashCode();
    }
}

Then you can use the overload 然后你可以使用过载

var groupedExampleList = exampleList.GroupBy(x => x.ListProp, 
                                             new ListOfBEqualityComparer());

Try this: 尝试这个:

GroupBy(x => String.Join(",", x.ListProp));

It will group by 0,1; 0,1; 0,1; 0,1,1; 0,1 它将按0,1; 0,1; 0,1; 0,1,1; 0,1分组0,1; 0,1; 0,1; 0,1,1; 0,1 0,1; 0,1; 0,1; 0,1,1; 0,1 0,1; 0,1; 0,1; 0,1,1; 0,1 accordingly. 0,1; 0,1; 0,1; 0,1,1; 0,1

I would approach this the following way: 我会通过以下方式来解决这个问题:

  1. Associate each child element (in ListProp property) with its parent 将每个子元素(在ListProp属性中)与其父元素相关联
  2. Group the parents by children 将孩子的父母分组
  3. Project the results 预测结果

var data = exampleList.SelectMany(a=>a.ListProp.Select(x=>new{Key = x.Prop.Number, Value = a}))
           .GroupBy(x=>x.Key)
           .Select(g=>new {Number = g.Key, Items = g.ToList()});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM