2010-09-03 6 views
2

J'ai un tableau 3DComment itérer sur Tableau chaîne 3D en C#

String[][,] cross = {new String[,]{{"1", "b", "b", "b"}, {"b", "c", "c", "c"}},new String[,]{{"2", "b", "b", "e"}, {"b", "c", "c", "d"}}} 

Comment itérer sur ce tableau.

Je veux itérer comme ceci

foreach(String[,] abc in cross) //abc must be the first/second 2D array 
    foreach(string[] arr in abc) //arr must hold {"1", "b", "b", "b"} (say) 
    { 
    } 

J'ai essayé, mais ne fonctionne pas.

+1

Vous avez actuellement un tableau en dents de scie de tableaux 2D. ** –

+1

Je suggère d'utiliser une liste d'objets ou des chaînes au lieu du tableau 3D, serait plus facile à itérer – Gage

Répondre

1

Compte tenu de votre en dents de scie de tableaux tableau 2D, vous procéderez à l'itération classique comme ce qui suit

foreach (string[,] array in cross) 
{ 
    for (int i = 0; i < array.GetLength(0); i++) 
    { 
     for (int j = 0; j < array.GetLength(1); j++) 
     { 
      string item = array[i, j]; 
      // do something with item 
     } 
    } 
} 
+0

Cela fonctionne sûrement.Une fissure. – Vinod

2

vous avez besoin 3 niveaux de imbriqués pour les boucles, une pour chaque dimension

2

Cela devrait fonctionner:

foreach (string s in cross.SelectMany(x => x.Cast<string>())) 
{ 
    // Code goes here. 
} 

MISE À JOUR: D'après vos commentaires, il semble que vous voulez pour votre énumération à un accord de point avec une string[] qui ressemble à ceci:

{"1", "b", "b", "b"} 

Le problème est: aucun tableau n'existe dans le tableau que vous avez déclaré. Cela peut prêter à confusion car il existe un chevauchement entre la syntaxe utilisée pour déclarer un tableau T[] et celle utilisée pour déclarer un tableau T[,].

Écrivons votre initialisation pour la rendre plus claire:

string[][,] cross = { 
    new string[,] { 
     {"1", "b", "b", "b"}, 
     {"b", "c", "c", "c"} 
    }, 
    new string[,] { 
     {"2", "b", "b", "e"}, 
     {"b", "c", "c", "d"} 
    } 
}; 

Ce que nous avons ici est deux string[,] tableaux de dimensions 4x2. L'expression {"1", "b", "b", "b"} ci-dessus ne représente pas un tableau individuel, mais plutôt les valeurs dans une dimension de votre tableau multidimensionnel.

Pour le comportement que vous semblez vouloir, Mark Cidade's answer est à droite sur l'argent: vous ne pouvez pas le faire avec un string[][,], mais vous pouvez le faire avec un string[][][].

string[][][] cross = new[] { 
    new[] { 
     new[] {"1", "b", "b", "b"}, 
     new[] {"b", "c", "c", "c"} 
    }, 
    new[] { 
     new[] {"2", "b", "b", "e"}, 
     new[] {"b", "c", "c", "d"} 
    } 
}; 

Déclarant cross de la manière ci-dessus vous permet d'effectuer les opérations suivantes:

foreach (string[][] abc in cross) 
{ 
    foreach (string[] arr in abc) 
    { 
     Console.WriteLine(string.Join(", ", arr)); 
    } 
} 

Ou, pour emprunter à ma suggestion originale:

foreach (string[] arr in cross.SelectMany(x => x)) 
{ 
    Console.WriteLine(string.Join(", ", arr)); 
} 

Sortie:

 
1, b, b, b 
b, c, c, c 
2, b, b, e 
b, c, c, d 
+0

chaque élément peut être extrait dans par ici. Autres suggestions sur mon exigence originale. – Vinod

+0

@Vinod: Désolé, vous avez raté ce que vous vouliez. Je vais mettre à jour. –

+0

+1 pour la simplicité et l'utilisation de LINQ – Gage

0
foreach(String[,] abc in cross) 
    foreach(string s in abc) //removed [] from inner loop 
    { 
     // do something with s 
    } 
} 
1

Un string[,] ne fonctionne pas de la même façon comme string[][] -c'est un tableau carré, pas un tableau des tableaux.Lorsque vous l'utilisez dans un communiqué foreach, le recenseur vous donnera une séquence de chaînes individuelles, semblable à ce qui suit:

foreach(string[,] abc in cross) 
for(int i=0; i < abc.GetLength(0); ++i) 
    for(int j=0; j < abc.GetLength(1); ++j) 
    { string str = abc[i,j]; 
    } 

Si vous voulez quelque chose de similaire à votre code d'itération, alors vous voulez un string[][][] au lieu d'un string[][,]:

string[][][] cross = { new string[][]{new string[]{"1", "b", "b", "b"}, new string[]{"b", "c", "c", "c"}} 
         ,new string[][]{new string[]{"2", "b", "b", "e"}, new string[]{"b", "c", "c", "d"}}}; 

foreach(string[][] abc in cross) 
    foreach(string[] arr in abc) 
    { 
    } 
1

tableau 3D devrait ressembler à ceci à ma façon:

string[, ,] arr = new string[,,]{ 
    { 
     {"a1", "b1", "c1"}, 
     {"a2", "b2", "c2"}, 
     {"a3", "b3", "c3"}, 
    },{ 
     {"a4", "b4", "c4"}, 
     {"a5", "b5", "c5"}, 
     {"a6", "b6", "c6"}, 
    } 
}; 

et i terating à travers tous les éléments un par un peut se faire de cette façon:

for (int i = 0; i < arr.GetLength(0); i++) 
{ 
    for (int j = 0; j < arr.GetLength(1); j++) 
    { 
     for (int k = 0; k < arr.GetLength(2); k++) 
     { 
      string s = arr[i, j, k]; 
     } 
    } 
} 
0

Cela ressemble à ce que vous voulez est de retrouver avec tableaux contenant les seconds éléments des tableaux 2D, regroupés par le premier élément . Donc, étant donné votre exemple, vous voulez obtenir des résultats comme celui-ci:

 
Iteration 1a: {"1", "b", "b", "b"} 
Iteration 1b: {"b", "c", "c", "c"} 
Iteration 2a: {"2", "b", "b", "e"} 
Iteration 2b: {"b", "c", "c", "d"} 

Il faut comprendre que cela ne peut être réalisé de manière efficace, car un tableau 2D ne sont pas stockées sous forme de plusieurs tableaux, mais plutôt comme un bloc unique de la mémoire. En mémoire, votre tableau regardera ce ceci:

 
"1", "b", "b", "b", "b", "c", "c", "c", "2", "b", "b", "e", "b", "c", "c", "d" 

Et lorsque vous accédez avec a[y, x], l'élément correct est choisi par y * a.GetLength(0) + x.

Si vous voulez vraiment un tableau de tableaux, alors vous devriez utiliser [][] au lieu de [,], ce que d'autres ont suggéré. Si, d'autre part, vous êtes bloqué avec le tableau multidimensionnel pour d'autres raisons, vous devrez construire ou simuler les tableaux internes.

Pour construire les réseaux internes:

foreach(string[,] square in cross) 
    for(int y = 0; y < square.GetUpperBound(0); y++){ 
     string[] inner = new string[square.GetLength(1)]; 
     for(int x = 0; x < inner.Length; x++) 
      inner[x] = square[y, x]; 
     // now do something with inner 
    } 

qui est assez inefficace, mais, si vous êtes mieux faire semblant. Si vous ne devez itérer plus tard, alors vous pouvez créer un dénombrable:

foreach(string[,] square in cross) 
    for(int y = 0; y < square.GetUpperBound(0); y++){ 
     var inner = GetEnumeratedInner(square, y); 
     // now do something with inner 
    } 

... 

static IEnumerable<string> GetEnumeratedInner(string[,] square, int y){ 
    for(int x = 0; x < square.GetUpperBound(1); x++) 
     yield return square[y, x]; 
} 

Si vous avez vraiment besoin d'y accéder par index, comme vous pouvez avec un tableau, puis une classe indexée fera l'affaire:

foreach(string[,] square in cross) 
    for(int y = 0; y < square.GetUpperBound(0); y++){ 
     var inner = new IndexedInner(square, y); 
     // now do something with inner 
    } 

... 

// this class should really implement ICollection<T> and System.Collections.IList, 
// but that would be too much unimportant code to put here 
class IndexedInner<T> : IEnumerable<T>{ 
    T[,] square; 
    int y; 

    public IndexedInner(T[,] square, int y){ 
     this.square = square; 
     this.y  = y; 
    } 

    public int Length{get{return square.GetLength(1);}} 

    public T this[int x]{ 
     get{return square[y, x];} 
     set{square[y, x] = value;} 
    } 

    public IEnumerator<T> GetEnumerator(){ 
     for(int x = 0; x < square.GetUpperBound(1); x++) 
      yield return square[y, x]; 
    } 
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){ 
     return GetEnumerator(); 
    } 
}