【问题标题】:Sum columns of a 2D array对二维数组的列求和
【发布时间】:2014-05-30 02:14:29
【问题描述】:

我有一个IEnumerable<IEnumerable<double>>,它基本上可以被认为是一个二维数组,我想做的是得到一个一维数组(或列表或其他),它是我原始集合中所有列的总数.换句话说,如果我有:

1   2   3   4
2   3   1   6
3   4   5   6
-------------
6   9   9   16

我想要最后一行(显然,这不是原始集合的一部分)。

有没有一种简单的方法可以使用 LINQ 来完成此操作,这样我就不必遍历整个事情了?我知道我可以使用.Sum 合计一行或一列,但我想合计每一行。

我看到一些其他问题(主要是处理数据库查询)建议使用group,但这似乎对我不起作用。我试过这个:

            var totals = from p in toTotal
                         group p by 1 into g
                         select g.Sum(t => t.First()); 

但这只是全部。

有没有聪明的方法来做到这一点?

编辑:例如,如果toTotal 被定义为:

    List<List<double>> toTotal = new List<List<double>>() {
        new List<double> {1,   2,   3,   4},
        new List<double> {2,   3 ,  1,   6},
        new List<double> {3 ,  4,   5 ,  6}
    };

【问题讨论】:

    标签: c# linq sum


    【解决方案1】:

    编辑:

    你可以这样做:

    List<List<double>> toTotal = new List<List<double>>() {
    new List<double> {1,   2,   3,   4},
    new List<double> {2,   3 ,  1,   6},
    new List<double> {3 ,  4,   5 ,  6}
                                    };
    
    var res = toTotal.Select(r => r.Select((t, i) => new { Column = i, Value = t }))
                     .SelectMany(r => r)
                     .GroupBy(r => r.Column)
                     .Select(grp => new
                     {
                         Column = grp.Key,
                         Sum = grp.Select(r => r.Value).Sum(),
                     });
    
    foreach (var item in res)
    {
        Console.WriteLine("Column: {0}, Sum: {1}", item.Column, item.Sum);
    }
    

    你会得到:

    Column: 0, Sum: 6
    Column: 1, Sum: 9
    Column: 2, Sum: 9
    Column: 3, Sum: 16
    

    旧答案

    您的 IEnumerable toTotal 的每个元素都需要 Sum,您可以像这样获得它:

    double[]totals = toTotal.Select(r => r.Sum()).ToArray();
    

    【讨论】:

    • 谢谢,但这不是我想要的。这将总计行,而不是列。我需要r[0], r[1]...r[n]的总和
    • @MattBurland,你能说明你是如何用一些值定义toTotal的吗?
    • @MattBurland,刚刚修改了我的答案,现在总结在专栏中。但我必须承认你的回答看起来很优雅。
    • 谢谢 Habib,我其实不知道你可以让 Select 像这样传递索引,这非常漂亮。
    【解决方案2】:

    好的。我想我已经成功了:

    var totals = toTotal.Aggregate((prev, next) => prev.Zip(next, (a, b) => a + b));
    

    诀窍是我一直在寻找 Fold(或 Reduce)函数,但在 LINQ 中它被称为 Aggregate

    这里有一个fiddle 显示这个和@Habib 的总行代码(用于比较)。与我在这里(以及我在实际代码中使用的)的唯一变化是我需要.ToList .Zip 的结果,因为对于这个测试用例,我有一个 List&lt;List&lt;double&gt;&gt; 这似乎让如果您没有显式转换为列表,则编译器。在我的实际代码中,toTotalIEnumerable&lt;IEnumerable&lt;double&gt;&gt;,不需要转换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-19
      • 2018-09-24
      • 2013-04-10
      • 2020-08-05
      • 1970-01-01
      • 2014-05-12
      相关资源
      最近更新 更多