【问题标题】:How to flatten 2 tier lists of objects and summing properties where other properties are common如何展平 2 层对象列表并汇总其他属性常见的属性
【发布时间】:2017-02-06 18:09:05
【问题描述】:

我意识到这个问题的名称令人困惑,所以让我来解释一下我的场景。

我有一个对象列表。该列表对每个用户都有一个条目。然后每个用户都有一个类别列表,每个类别都有一个类别 id,以及一些已经计算过的值。我需要在一个类别列表中展平我的对象,其中每个类别的属性已被求和。每个用户在其列表中的类别数量相同,并且每个类别都将出现在每个用户的列表中(换句话说,每个用户将拥有相同的类别列表,只是计算出的属性不同)。

我的课程是:

public class category {
     public int categoryID { get; set; }
     public decimal categoryValue { get; set; }
     public decimal categoryValue2 { get; set; }
}

public class user {
    public List<category> categories { get; set; }
}

我需要实现的是通过使用 Linq(或任何最有效的方式)将数据展平为单个列表,其中类别仍按其各自的 ID 拆分,但 categoryValue 和 categoryValue2 已分别总计。因此,所有用户的每个类别的总价值为 2。

我尝试过如下循环:

List<category> categoryTotals = new List<category> {};
foreach (category loopCategory in users[0].categories) {
    category currentCategory = new category();
    category = users.Select(x => x.categories).Where(y=>y.categoryID== loopCategory.categoryID)).Select(t => new {t....
}

但是 t 给了我 linq 函数,而不是我想要求和的属性。

我也尝试过仅使用 linq 的类似方法,但是在执行 SelectMany 之后,再执行 GroupBy,随后的 select 语句再次不会公开类别列表的属性。

非常感谢!

【问题讨论】:

  • users.SelectMany(u =&gt; u.categories) 将为您提供所有用户的所有类别的单一平面序列。
  • @Ed Plunkett 指出。但是,然后我需要按 ID 对这些类别的平面序列进行分组,并计算每个类别的值。

标签: c# linq list object


【解决方案1】:

这是你想要的吗?

var groupSums = 
    from g in users.SelectMany(u => u.categories).GroupBy(c => c.categoryID)
    select new
    {
        categoryID = g.Key,
        CategoryValueSum = g.Sum(c => c.categoryValue),
        CategoryValue2Sum = g.Sum(c => c.categoryValue2),
    };

users.SelectMany(u =&gt; u.categories).GroupBy(c =&gt; c.categoryID) 为您提供Group&lt;category&gt; 对象的序列。每个都有一个Key 属性等于组的categoryID,并且还实现IEnumerable&lt;category&gt;

整个过程为您提供了一个具有categoryID 属性的匿名对象的平面序列,以及两个用于两个类别值之和的 sum 属性。匿名类可能会受到限制,因此根据您对结果的处理方式,您可能需要为此编写一个新的快速类。

当然,如果您出于某种原因需要保留结果,请在结果上致电ToList()

【讨论】:

    【解决方案2】:

    经过测试,它看起来像这样。您将获得包含所需聚合结果的分组类别列表。

        var cats = users.SelectMany(x => x.categories).GroupBy(x => x.CategoryID)
            .Select(x => new Category()
            {
                CategoryID = x.Key,
                CategoryValue = x.Sum(y => y.CategoryValue),
                CategoryValue2 = x.Sum(y => y.CategoryValue2)
            });
    

    【讨论】:

      【解决方案3】:

      您可以使用 LINQ SelectMany 方法与 GroupBy 结合使用

      var sumList = users
          .SelectMany(u => u.categories)
          .GroupBy(c => c.categoryID)
          .Select(g => new category()
          {
             categoryID = g.Key,
             categoryValue = g.Sum(z => z.categoryValue),
             categoryValue2 = g.Sum(z => z.categoryValue2),
          })
         .ToList();
      

      这将为所有用户返回 List&lt;category&gt;categoryValuecategoryValue2

      【讨论】:

      • 谢谢!像魅力一样工作。看到它时很简单,但是经过几个小时的辛勤工作(我对 Linq 还很陌生),我似乎不可能。我被困在为什么 Group By 给我一个没有 id 的枚举,不知道 Key 是需要什么。我进一步调整了这个(很遗憾我不能发布实际代码)按一个复杂的键分组,这样我就可以获得类别名称(不包括在问题中)和类别顺序。
      • @EugenedeLange 是的,使用 GroupBy 这个IGroupping&lt;T&gt; 接口的返回类型似乎很棘手,但如果你知道怎么做,那就小菜一碟了。
      猜你喜欢
      • 1970-01-01
      • 2015-02-03
      • 1970-01-01
      • 2013-10-26
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多