【问题标题】:Calculate averages of multiple IEnumerable with same item count计算具有相同项目数的多个 IEnumerable 的平均值
【发布时间】:2018-10-17 00:34:50
【问题描述】:

假设我们有多个 IEnumerables 的相同项目计数

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 }

可枚举的数量可能会有所不同(即不固定为四个)。

每个可枚举项中的项目数可能会有所不同(即不固定为三个),但对于该特定实例的所有可枚举项来说都是相同的。

【问题讨论】:

    标签: c# linq average ienumerable


    【解决方案1】:

    更新以响应编辑

    如果你有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&lt;IEnumerable&lt;int&gt;&gt;,请将.Select 行更改为:.Select(e =&gt; e.Select(v =&gt; v.Item).Average())(但根据您的评论,我认为情况并非如此)。

    1. 使用.SelectMany 将列表展平为包含项目及其子数组索引的对象(因此10 和11 将具有Index 0 等)。
    2. 按索引分组。
    3. 使用.Select 选择每个分组的平均值。

    Try it online

    Try it online with question data

    原答案

    您可以使用.Zip 组合两个列表并计算平均值:

    var averages = items1
                      .Zip(items2, (a, b) => (a+b)/2.0)
                      .ToArray();
    

    Try it online

    【讨论】:

    • 谢谢约翰!我想我过于简单化了我的问题。 Zip 与两个 IEnumerables 一起工作,但如果有两个以上(因此是多个)怎么办?基本上我有一个IEnumerable&lt;IEnumerable&lt;Item&gt;&gt;。你介意我更新我的问题吗?
    • 天才!我可能花了几天时间才弄清楚这一点。 :)) 非常感谢!
    【解决方案2】:

    由于您对压缩两个以上的IEnumerable&lt;T&gt;s 感兴趣,这里有一个扩展方法 (ZipAll),它展示了如何将多个 IEnumerable&lt;T&gt; 压缩在一起。实际上,这会旋转数据,使列变为行。

    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2017-02-06
      • 1970-01-01
      • 2022-08-17
      • 2021-04-06
      相关资源
      最近更新 更多