【问题标题】:Sum multidimensional array over dimensions [closed]在维度上求和多维数组[关闭]
【发布时间】:2018-08-06 11:43:34
【问题描述】:

假设我有这样的锯齿状数组(3 维)。

int[][][] tab = new int[][][] 
{
     new int[][]
     {
         new int[] {1, 2, 3},
         new int[] {4, 5, 6}
     },
     new int[][]
     {
         new int[] {7, 8, 9},
         new int[] {10, 11, 12}
     }
 };

我想在第一维上求和。我想得到:

new int[][] 
{
    new int[] {1+7, 2+8, 3+9},
    new int[] {4+10, 5+11, 6+12}
};

我想在第二维度上求和。

new int[][] 
{
    new int{1+4, 2+5, 3+6},
    new int{7+10, 8+11, 9+12}
}

这两件事怎么做?我不想要循环,而是想要 LINQ 表达式。

【问题讨论】:

  • "I don't want loops, but rather LINQ expression" -- 你认为 LINQ 在后台做什么?
  • 你没有多维数组,你有锯齿状数组。 3 维数组看起来像 int[3,3,3]
  • 另外,这段代码甚至无法编译
  • 我知道如何使用循环,但我希望我的代码更短 - 你想要更短的代码是什么?您还没有发布任何循环代码。
  • 你没有要求 帮助,你要求有人为你做这项工作。你没有在你的问题中尝试解决这个问题,你已经向我们规定你只想要 LINQ 答案,尽管这不是最好的选择。您应该尝试解决问题。这就是为什么您需要在问题中包含minimal reproducible example

标签: c# arrays linq sum jagged-arrays


【解决方案1】:

这很像 APL Reduction 运算符,它有一个很酷的功能,可以让您在任何维度上进行归约(例如 +/tab+/[1]tab)。

在第一个维度上,LINQ 已经有一个等价的 Aggregate 函数。使用其他一些扩展功能,您可以使用它来做您想做的事情:

public static class Ext {
    public static int[] Add(this int[] v1, int[] v2) => v1.Zip(v2, (v1v, v2v) => v1v+v2v).ToArray();
    public static int[][] Add(this int[][] a1, int[][] a2) => a1.Zip(a2, (a1r, a2r) => a1r.Add(a2r)).ToArray();

    public static TSource Reduce<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func) => source.Aggregate(func);
    public static IEnumerable<T> Reduce2<T>(this IEnumerable<IEnumerable<T>> src, Func<T, T, T> op) => src.Select(s => s.Reduce(op));
}

我将 Aggregate 重命名为 Reduce 以保持 APL 主题。

使用Reduce 函数,您可以减少第一维,添加二维数组:

var ans1 = tab.Reduce((a1, a2) => a1.Add(a2));

使用Reduce2 函数,您可以减少第二维,添加一维数组:

var ans2 = tab.Reduce2((a1, a2) => a1.Add(a2)).ToArray();

由于我在IEnumerable 上写了Reduce/Reduce2 是通用的,因此您必须将Reduce2 答案转换回数组。

【讨论】:

    【解决方案2】:

    由于使用了交错数组,因此每个组内最小数组的长度用于索引以避免IndexOutOfRangeException

    // I want to sum it over first dimension.
    var firstDimensionSums = tab
        .Aggregate((a, b) => Enumerable.Range(0, Math.Min(a.Length, b.Length))
            .Select(i0 => Enumerable.Range(0, Math.Min(a[i0].Length, a[i0].Length))
                .Select(i1 => a[i0][i1] + b[i0][i1])
                .ToArray())
            .ToArray());
    
    // I want to sum it over second dimension.
    var secondDimensionSums = tab
        .Select(nested => nested
            .Aggregate((a,b) => Enumerable.Range(0, nested.Min(x => x.Length))
                .Select(index => a[index] + b[index])
                .ToArray()))
        .ToArray();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 2013-05-22
      • 2023-02-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      相关资源
      最近更新 更多