2009-12-07 11 views
6

Quiero el método de extensión de escritura para la matriz rectangular multidimensional de relleno. Yo sé cómo hacerlo de la matriz con un número fijo de mediciones:Método de extensión para la matriz rectangular de relleno en C#

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; 
} 

¿Puedo escribir un método de relleno para toda matriz rectangular multidimensional?

+0

Todos sus ejemplos son matrices rectangulares, no matrices irregulares. ¿Estás seguro de que quieres resolver el problema de las matrices irregulares? –

+0

Lo siento, cometí un error en mi pregunta. Ya está arreglado – AndreyAkinshin

Respuesta

5

Puede cambiar el parámetro de dimensión fija a un parámetro de matriz para que pueda poner la extensión en cualquier matriz. Luego utilicé la recursión para iterar a través de cada posición de la matriz.

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); 
     } 
    } 
} 
+0

Buena solución. ¿Cómo modificaría su solución para hacer que funcione en una matriz multidimensional de * punteros a entero *, en código inseguro? –

1

he aquí una solución que no utiliza recursión (y es menos complejo):

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); 
     } 
    } 

Esto se modela a partir de la System.Array.ArrayEnumerator. Esta implementación debería tener un nivel de corrección similar a la de ArrayEnumerator y (en función de unos pocos controles puntuales) parece funcionar bien.

Cuestiones relacionadas