2009-12-07 15 views
6

Voglio il metodo di estensione di scrittura per riempire array rettangolari multidimensionali. So come si fa per la matrice con un numero fisso di misure:Metodo di estensione per riempire array rettangolari in 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; 
} 

Posso scrivere un fill-metodo per tutta matrice rettangolare multidimensionale?

+0

Tutti gli esempi sono array rettangolari, non matrici frastagliate. Sei sicuro di voler risolvere il problema con gli array frastagliati? –

+0

Mi dispiace, ho fatto un errore nella mia domanda. Già risolto – AndreyAkinshin

risposta

5

È possibile modificare il parametro di dimensione fissa in un parametro Array in modo da poter inserire l'estensione su qualsiasi Array. Quindi ho usato la ricorsione per scorrere ogni posizione dell'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); 
     } 
    } 
} 
+0

Bella soluzione. Come modificheresti la tua soluzione per farlo funzionare su un array multidimensionale di * puntatori a numero intero *, in codice non sicuro? –

1

Ecco una soluzione che non utilizza la ricorsione (ed è meno complessa):

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

Questo è modellato dalla System.Array.ArrayEnumerator. Questa implementazione dovrebbe avere un livello simile di correttezza come ArrayEnumerator e (basato su alcuni controlli a campione) sembra funzionare bene.