假设我们有多个IEnumerable
,它们的项目数相同
var multipleEnumerables = new[]
{
new[] { 10, 20, 30 }
new[] { 11, 21, 31 }
new[] { 12, 22, 32 }
new[] { 13, 23, 33 }
}
我如何获得使用LINQ的平均值,将得出以下结果:
new[] { 11.5, 21.5, 31.5 }
可枚举的数量可能有所不同(即不固定为四个)。
每个可枚举项的数量可能有所不同(即不固定为三个),但对于该特定实例的所有可枚举项,其数量都是相同的。
答案 0 :(得分:4)
更新以响应编辑
如果您有IEnumerable<IEnumerable<Item>>
,则可以使用以下内容:
IEnumerable<IEnumerable<Test>> multipleEnumerables = new[] {
new [] { new Test { Value = 10 }, new Test { Value = 20 } },
new [] { new Test { Value = 11 }, new Test { Value = 21 } }
};
var averages = multipleEnumerables
.SelectMany(e => e.Select((v, i) => new { Index = i, Item = v }))
.GroupBy(e => e.Index)
.Select(e => e.Select(v => v.Item.Value).Average())
.ToArray();
如果您有一个简单的IEnumerable<IEnumerable<int>>
,请将.Select
行更改为:.Select(e => e.Select(v => v.Item).Average())
(但根据您的评论,我认为不是这种情况)。
.SelectMany
将列表平整为包含该项目及其子数组索引的对象(因此10和11将具有Index
0,依此类推。).Select
从每个分组中选择平均值。Try it online with question data
原始答案
您可以使用.Zip
合并两个列表并计算平均值:
var averages = items1
.Zip(items2, (a, b) => (a+b)/2.0)
.ToArray();
答案 1 :(得分:2)
由于您希望压缩两个以上的IEnumerable<T>
,因此,这里有一个扩展方法(ZipAll
),该方法显示了如何将多个IEnumerable<T>
一起压缩。实际上,这可以旋转数据,使列变为行。
public static class ZipEx
{
public static IEnumerable<IEnumerable<T>> ZipAll<T>(
this IEnumerable<IEnumerable<T>> src)
{
return src
.Aggregate(
(IEnumerable<IEnumerable<T>>)null,
(acc, curr) => acc == null
? curr.Select(x => x.ToEnumerable())
: acc.Zip(curr, (a, c) => a.Append(c)));
}
public static IEnumerable<T> ToEnumerable<T>(this T item)
{
yield return item;
}
}
使用此ZipAll
方法,现在很容易:
var averages = multipleEnumerables.ZipAll().Select(x => x.Average()); //.ToArray()