使用LINQ分组将多个int列表汇总为一个

时间:2018-06-21 20:20:50

标签: c# .net linq

我有物品清单。

项目的指定方式如下:

public class Item
{
    public List<decimal> Values { get; set; }

    public string GroupingKey { get; set; }

    public List<int> Cycle { get; set; }
}

我想通过对键进行分组,对项实例列表进行分组,并按列表中的索引对值进行求和,然后添加到一个列表中。每个组的周期列表相同,因此只需将其添加到新组中即可。

例如,以下列表:

List<Items>
{
    Values { 2, 3, 5 },
    GroupingKey = "P23",
    Cycle { 1, 2, 3, 4 }
},
{
    Values { 10, 20, 30 },
    GroupingKey = "P23",
    Cycle { 1, 2, 3, 4 }
},
{
    Values { 10, 20, 30 },
    GroupingKey = "P24",
    Cycle { 1, 2, 3, 4 }
}

最终看起来像这样:

List<Items>
{
    Values { 12, 23, 35},
    GroupingKey = "P23",
    Cycle { 1, 2, 3, 4}
},
{
    Values { 10, 20, 30},
    GroupingKey = "P24",
    Cycle { 1, 2, 3, 4}
}
具有相同键的

Item实例可以更多,而不仅仅是两个。 关于如何使用LINQ解决此问题的任何想法?

谢谢。

2 个答案:

答案 0 :(得分:1)

您可以使用一堆GroupBySelect来实现:

var result = list.GroupBy(i => i.GroupingKey).ToList().Select(group => new Item
{
    Values = group.SelectMany(item => item.Values
                .Select((value, index) => new {value, index}))
                      .GroupBy(item => item.index)
                      .Select(a => a.Sum(e => e.value)).ToList(),
    GroupingKey = group.Select(i => i.GroupingKey).FirstOrDefault(),
    Cycle = group.Select(i => i.Cycle).FirstOrDefault()
});

答案 1 :(得分:-1)

您需要的是Enumerable.Zip方法,该方法可跨多个序列工作。不幸的是,LINQ没有提供这种功能,因此我们必须投影索引并手动求和元素。

    var merged = items
        .GroupBy(x => x.GroupingKey)
        .Select(grp => new Item
        {
            Values = Enumerable
                .Range(0, grp.Max(x => x.Values.Count))
                .Select(i => grp.Sum(x => x.Values.Count > i ? x.Values[i] : 0))
                .ToList(),
            GroupingKey = grp.Key,
            Cycle = grp.First().Cycle   // can add check that others are identical
        })
        .ToList();