c# - LINQ:子 IEnumerable 的平均值

标签 c# linq

我有一个看起来像这样的数据集:

[
{
 "Size" : "Small",
 "Details" :
  {
    "Detail 1" : 1.0,
    "Detail 1" : 1.0,
    "Detail 2" : 1.0,
  }
},
{
 "Size" : "Small",
 "Details" :
  {
    "Detail 1" : 2.0,
    "Detail 1" : 3.0,
    "Detail 2" : 4.0,
  }
},
{
 "Size" : "Medium",
 "Details" :
  {
    "Detail 1" : 1.0,
    "Detail 1" : 1.0,
    "Detail 2" : 1.0,
    "Detail 3" : 1.0,
  }
},
//... etc
]

对于具有相同“尺寸”的所有项目,我想单独总结匹配的“详细信息”条目,然后将它们平均到像“尺寸”d 个项目。即:

[
{
 "Size" : "Small",
 "Details" :
 {
    "Detail 1" : 3.5,
    "Detail 2" : 2.5,     // Average of the summation of the two 'small' items in original data set
 },
    {
     "Size" : "Medium",
     "Details" :
      {
        "Detail 1" : 2.0, // Average of the two details for medium.
        "Detail 2" : 1.0,
        "Detail 3" : 1.0,
      }
    },
]

我得到的代码是这样的,但我一直在弄清楚如何对嵌套集进行平均。任何指针将不胜感激。

我的代码,到目前为止。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{

    class ItemWithDetails
    {
        public string Size;
        public List<KeyValuePair<string, double>> Details { get; private set; }

        public ItemWithDetails(string size)
        {
            Size = size;
            Details.Add(new KeyValuePair<string, double>("Detail 1", 1));
            Details.Add(new KeyValuePair<string, double>("Detail 1", 1));
            Details.Add(new KeyValuePair<string, double>("Detail 2", 1));
            Details.Add(new KeyValuePair<string, double>("Detail 2", 1));
            Details.Add(new KeyValuePair<string, double>("Detail 2", 1));
            Details.Add(new KeyValuePair<string, double>("Detail 3", 1));

            if (size == "Large")
            {
                Details.Add(new KeyValuePair<string, double>("Detail 3", 1));
                Details.Add(new KeyValuePair<string, double>("Detail 3", 1));
                Details.Add(new KeyValuePair<string, double>("Detail 3", 1));
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var testData = new List<ItemWithDetails>()
            {
                new ItemWithDetails("Small"),
                new ItemWithDetails("Small"),
                new ItemWithDetails("Medium"),
                new ItemWithDetails("Medium"),
                new ItemWithDetails("Medium"),
                new ItemWithDetails("Large"),
                new ItemWithDetails("Large"),
                new ItemWithDetails("Large"),
            };

            // Trying to get the average of each detail, per size.

            var detailSummed = from item in testData
                               select new
                               {
                                   size = item.Size,
                                   detailsSummed = from detail in item.Details
                                                   group detail by detail.Key into detailGroup
                                                   select new
                                                   {
                                                       detailName = detailGroup.Key,
                                                       detailSum = detailGroup.Sum(a => (a.Value))
                                                   }
                               };

            var averageAcrossItems =    from item in detailSummed
                                        group item by item.size into itemGroup
                                        select new 
                                        {
                                            size = itemGroup.Key,
                                            detailsAveraged = // not sure how I can average across items, while at this level.  Do I have to flatten it?
                                        }

        }
    }
}

更新:

使用 Adam Mills 代码,我更接近于合并两个单独的 LINQ 查询。能否将其制作成一个有望更具可读性的 LINQ 查询?

        var detailSummed = from item in testData
                           select new
                           {
                               size = item.Size,
                               detailsSummed = from detail in item.Details
                                               group detail by detail.Key into detailGroup
                                               select new
                                               {
                                                   detailName = detailGroup.Key,
                                                   detailSum = detailGroup.Sum(a => (a.Value))
                                               }
                           };

        var test2 = detailSummed.GroupBy(x => x.size)
                                .Select(y =>
                                           new
                                           {
                                               Size = y.Key,
                                               DetailAverages = y   .SelectMany(x => x.detailsSummed)
                                                                    .GroupBy(x => x.detailName)
                                                                    .Select(x => new KeyValuePair<string, double>(x.Key, x.Average(c => c.detailSum)))
                                           });

最佳答案

 items.GroupBy(x => x.Size)
                .Select(y =>

                        new
                            {
                                Size = y.Key,
                                Details = y.SelectMany(x => x.Details)
                                            .GroupBy(x => x.Key)
                                            .Select(x => new
                                                             {
                                                                 Key = x.Key,
                                                                 Average = x.Average(c => c.Value),
                                                                 Sum = x.Sum(c => c.Value)
                                                             })
                            });

关于c# - LINQ:子 IEnumerable 的平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13362819/

相关文章:

c# - ExcelAsyncUtil.Observe - 在 Excel 中创建运行时钟

.net - NHibernate.Linq : session becomes dirty after select

c# - 如何订购无序序列

c# - 使用 LINQ 从不同的组中选择重复值

c# - LINQ OrderByDescending 传递字符串值

c# - StartCoroutine 函数不适用于 android,但在 Unity 编辑器中运行良好

c# - 如何测量页面时间负载?

javascript - 使用javascript设置cookie并在服务器端读取它

c# - 为什么 ExecuteStoredProcedure 有效而下面的代码无效?

c# - Entity Framework 中 LINQ 投影的可重用计算(代码优先)