This is a lot like the APL Reduction operator, which has a cool feature of letting you reduce over any dimension (e.g. +/tab
versus +/[1]tab
).
Over the first dimension, LINQ has an equivalent already, the Aggregate
function. With some other extension functions, you can use it to do what you want:
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));
}
I renamed Aggregate
to Reduce
to keep with the APL theme.
With the Reduce
function, you can reduce across the first dimension, adding the 2D arrays:
var ans1 = tab.Reduce((a1, a2) => a1.Add(a2));
With the Reduce2
function, you can reduce across the second dimension, adding the 1D arrays:
var ans2 = tab.Reduce2((a1, a2) => a1.Add(a2)).ToArray();
Since I wrote Reduce
/Reduce2
to be generic on IEnumerable
, you have to convert the Reduce2
answer back to an array.