次のようなデータセットがあります。
[
{
"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
]
同じ「サイズ」のすべてのアイテムについて、一致する「詳細」エントリを個別に合計し、「サイズ」のアイテムのようにそれらを平均したいと思います。すなわち:
[
{
"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 のコードを使用して、2 つの個別の LINQ クエリを組み合わせることで、さらに近づけることができました。これを、より読みやすい 1 つの 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)))
});