Traversing an n-dimensional array using a higher order method

Here we use the extension method each , which can be used to apply Action<int, int, T> to each element and the corresponding indices of the two-dimensional array:

 static public void each<T>(this T[,] a, Action<int, int, T> proc) { for (int i = 0; i < a.GetLength(0); i++) for (int j = 0; j < a.GetLength(1); j++) proc(i, j, a[i, j]); } 

Usage example:

 var arr = new int[3, 3]; arr.each((x, y, val) => arr[x, y] = x + y); arr.each((x, y, val) => Console.WriteLine("{0} {1} {2}", x, y, val)); 

Is it possible to write a version of each that can work with arrays of any rank?

+4
source share
1 answer

It is not possible to specify a generic number with an arbitrary number of parameters, so you will have to pass an array of indexes to your procedure. The easiest way to do this is probably with recursion, so here's a recursive way to do this. Since it uses an optional parameter, it requires C # 4.0 or higher.

 static class Arrays { public static void Each<T>(this Array a, Action<int[], T> proc, int[] startAt = null) { int rank = startAt == null ? 0 : startAt.Length; int[] indices = new int[rank + 1]; if (rank > 0) startAt.CopyTo(indices, 0); for (int i = a.GetLowerBound(rank); i <= a.GetUpperBound(rank); i++) { indices[rank] = i; if (rank == a.Rank - 1) proc(indices, (T)a.GetValue(indices)); else Each(a, proc, indices); } } } 

You would call it like this:

 var array = new int[1, 2, 3, 4, 5]; array.Each<int>((indices, data) => array.SetValue(indices.Sum(), indices)); array.Each<int>((indices, data) => Console.WriteLine(string.Join(", ", indices) + ": " + data)); 
+3
source

Source: https://habr.com/ru/post/1381845/


All Articles