Extension method for rectangular fill in C #

I want to write an extension method to populate a multidimensional rectangular array. I know how to do this for an array with a fixed number of dimensions:

public static void Fill<T>(this T[] source, T value) { for (int i = 0; i < source.Length; i++) source[i] = value; } public static void Fill<T>(this T[,] source, T value) { for (int i = 0; i < source.GetLength(0); i++) for (int j = 0; j < source.GetLength(1); j++) source[i, j] = value; } public static void Fill<T>(this T[,,] source, T value) { for (int i = 0; i < source.GetLength(0); i++) for (int j = 0; j < source.GetLength(1); j++) for (int k = 0; k < source.GetLength(2); k++) source[i, j, k] = value; } 

Is it possible to write one fill method for an entire multidimensional rectangular array?

+6
arrays c #
source share
2 answers

You can change a fixed dimension parameter to an Array parameter so that you can put the extension on any array. Then I used recursion to repeat each position of the array.

 public static void Fill<T>(this Array source, T value) { Fill(0, source, new long[source.Rank], value); } static void Fill<T>(int dimension, Array array, long[] indexes, T value) { var lowerBound = array.GetLowerBound(dimension); var upperBound = array.GetUpperBound(dimension); for (int i = lowerBound; i <= upperBound; i++) { indexes[dimension] = i; if (dimension < array.Rank - 1) { Fill(dimension + 1, array, indexes, value); } else { array.SetValue(value, indexes); } } } 
+5
source share

Here's a solution that doesn't use recursion (and less complicated):

  public static void FillFlex<T>(this Array source, T value) { bool complete = false; int[] indices = new int[source.Rank]; int index = source.GetLowerBound(0); int totalElements = 1; for (int i = 0; i < source.Rank; i++) { indices[i] = source.GetLowerBound(i); totalElements *= source.GetLength(i); } indices[indices.Length - 1]--; complete = totalElements == 0; while (!complete) { index++; int rank = source.Rank; indices[rank - 1]++; for (int i = rank - 1; i >= 0; i--) { if (indices[i] > source.GetUpperBound(i)) { if (i == 0) { complete = true; return; } for (int j = i; j < rank; j++) { indices[j] = source.GetLowerBound(j); } indices[i - 1]++; } } source.SetValue(value, indices); } } 

This is modeled using System.Array.ArrayEnumerator. This implementation should have a similar level of correctness, since ArrayEnumerator and (based on several random checks) works fine.

+1
source share

All Articles