【问题标题】:Average of 3 IEnumerables3 个 IEnumerables 的平均值
【发布时间】:2012-02-20 11:39:04
【问题描述】:

我需要平均 3 个 IEnumerable 集合并创建一个新的 IEnumerable,结果如下:

var result1 = GetResult1()//Returns an enumerable collection having elements 1,2,3,4

var result2 = GetResult2()//Returns an enumerable collection having elements 3,4,2,6

var result3 = GetResult3()//returns an enumerable collection having elements 2,5,1,6

//I need to create a collection which has the averages of the above results as below:

var result4 = GetResult4()//Should return 2.00,3.67,2.33,5.33.
  • 每个结果将具有相同数量的元素,即 result1、result2、result3 将具有相同数量的元素(在本例中为 4,但实际上它的范围可以到 1500)。

  • 结果中的每个元素对应于结果的平均值,即在 result4 集合中,第一个元素将是 1,3,2 的平均值,对应于 result1,result2 中第一个元素的平均值, result3 分别和以后。

  • 生成的集合应将小数位四舍五入为 2。

一个明显的答案是遍历集合中的每个元素并手动创建结果集合中的元素(即通过 for 循环),但是我想避免它,因为结果将在每个集合中包含接近 1500 个元素并希望使用 LINQ 进行某种惰性求值。

你能帮我指点一下吗?

干杯, -迈克

【问题讨论】:

    标签: c# linq ienumerable


    【解决方案1】:

    如果您使用的是 .NET 4,您可以在这里使用Enumerable.Zip 以获得良好效果:

    var averages = result1.Zip(result2, (x, y) => x + y)
                          .Zip(result3, (xy, z) => (xy + z) / 3.0d)
                          .ToList();
    

    这不会进行任何舍入 - 这通常更适合 格式化 步骤。请注意,无论如何,这些值只能以 0、0.33 或 0.67 结尾,因为您只能除以 3。这里我使用了 double,但另一种选择是使用 decimal - 这取决于值真的很刻薄。

    【讨论】:

    • 想象一个斐波那契数列,其中包含每个集合中该数列的前 1000 个数,即 result1、result2 和 result3 每个都包含该数列。我相信你会对 result4 使用小数,对吗?
    • @Mike:说实话,我不知道。那里没有“单位”,真的……用“身高”和“薪水”等具体数量更容易判断。你可以只返回总和,而不是把它除以三吗?毕竟是相同的数据,只是按比例缩放...
    【解决方案2】:

    实现此目的的一种方法是编写一个方法,该方法采用列表列表并执行必要的工作。比如:

     private static IEnumerable<double> AverageOfLists(params IEnumerable<double>[] values)
     {
         var lists = values.Select(v => v.ToList()).ToArray();
    
         for(var i=0;i<lists[0].Count;i++)
         {
             var sum = 0.0;
             for(var j=0;j<lists.Length;j++)
             {
                 sum+= lists[j][i];
             }
             yield return sum/lists.Length;
         }
     }
    

    然后使用

    var result4 = AverageOfLists(result1,result2,result3);
    

    现场示例:http://rextester.com/IGOSE98291

    注意:由于@Jon 提到的相同原因,不包括舍入;舍入是一个格式化/显示步骤。

    【讨论】:

    • 并不是说这需要将所有数据都拉入内存,但实际上并没有必要。这一切都可以以流媒体的方式完成。
    猜你喜欢
    • 2014-07-19
    • 2018-01-21
    • 2019-12-16
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 1970-01-01
    相关资源
    最近更新 更多