简体   繁体   中英

Traversal of n-dimensional array via a higher-order method

Here's an extension method each which can be used to apply an Action<int, int, T> to every element and it's corresponding indices of a 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]);
}

Example usage:

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 which can work on arrays of any rank?

There's no way to specify a generic with an arbitrary number of parameters, so you would have to pass your procedure an array of indices. The easiest way to do this is probably with recursion so here's a recursive way to do it. 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));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM