2012-04-05 2 views
18

Depuis, j'utilise cette boucle pour parcourir les éléments d'un tableau, ce qui fonctionne bien même si je mets des objets avec diverses propriétés à l'intérieur.For loop dans un tableau javascript multidimensionnel

var cubes[]; 

for (i in cubes){ 
    cubes[i].dimension 
    cubes[i].position_x 
    ecc.. 
} 

Maintenant, supposons que les cubes [] est déclaré cette façon

var cubes[][]; 

Puis-je faire dans Javascript? Comment puis-je alors itérer automatiquement

cubes[0][0] 
cubes[0][1] 
cubes[0][2] 
cubes[1][0] 
cubes[1][1] 
cubes[1][2] 
cubes[2][0] 
ecc... 

Pour contourner ce problème, je peux déclarer:

var cubes[]; 
var cubes1[]; 

et séparément travailler avec les deux tableaux. Est-ce une meilleure solution?

Répondre

36

Vous pouvez faire quelque chose comme ceci:

var cubes = [ 
[1, 2, 3], 
[4, 5, 6],  
[7, 8, 9], 
]; 

for(var i = 0; i < cubes.length; i++) { 
    var cube = cubes[i]; 
    for(var j = 0; j < cube.length; j++) { 
     display("cube[" + i + "][" + j + "] = " + cube[j]); 
    } 
} 

travail jsFiddle:

La sortie de ce qui précède:

cube[0][0] = 1 
cube[0][1] = 2 
cube[0][2] = 3 
cube[1][0] = 4 
cube[1][1] = 5 
cube[1][2] = 6 
cube[2][0] = 7 
cube[2][1] = 8 
cube[2][2] = 9 
+0

Votre solution fonctionne uniquement avec les baies 2D, mais j'ai trouvé un moyen de faire une boucle sur les baies avec un nombre quelconque de dimensions: http://stackoverflow.com/a/15854485/975097 –

+0

@AndersonGreen OP recherchait spécifiquement Tableaux 2D, donc la réponse ci-dessus. Merci pour le lien - espérons que cela aidera quelqu'un à la recherche d'une solution similaire dans le futur! –

+0

Salut, comment obtenir le résultat comme «1,4,7», «1,4,8», «1,4,9», «1,5,7», «1,5,8» ... – Bharadwaj

1

JavaScript ne possède pas de telles déclarations. Il serait:

var cubes = ... 

quel que soit

Mais vous pouvez faire:

for(var i = 0; i < cubes.length; i++) 
{ 
    for(var j = 0; j < cubes[i].length; j++) 
    { 

    } 
} 

Notez que JavaScript permet des tableaux déchiquetés, comme:

[ 
    [1, 2, 3], 
    [1, 2, 3, 4] 
] 

puisque les tableaux peuvent contenir tout type d'objet, y compris un tableau de longueur arbitraire.

Comme l'a noté MDC:

"for..in ne doit pas être utilisé pour itérer sur un tableau où l'ordre d'index est important"

Si vous utilisez votre syntaxe d'origine, il n'est pas garanti que les éléments seront visités dans un ordre numérique.

12
var cubes = [["string", "string"], ["string", "string"]]; 

for(var i = 0; i < cubes.length; i++) { 
    for(var j = 0; j < cubes[i].length; j++) { 
     console.log(cubes[i][j]); 
    } 
} 
+0

Il a demandé comment l'itérer. –

+0

Et il a demandé "Puis-je faire cela en javascript?" – binarious

+0

Vous avez modifié votre réponse après mon commentaire. Votre message original n'avait rien à propos de l'itération. –

6

Essayez ceci:

var i, j; 

for (i = 0; i < cubes.length; i++) { 
    for (j = 0; j < cubes[i].length; j++) { 
     do whatever with cubes[i][j]; 
    } 
} 
+0

Cela va créer des variables globales. –

+3

Ajout de var i, j; En toute justice, il n'a pas dit: «Ne créez pas de variables globales». ;-) –

3

Un moyen efficace de boucle sur un tableau est le built-in array method .map()

Pour un tableau 1 dimensions, il ressemblerait à ceci:

function HandleOneElement(Cuby) { 
    Cuby.dimension 
    Cuby.position_x 
    ... 
} 
cubes.map(HandleOneElement) ; // the map function will pass each element 

pour un réseau bidimensionnel:

cubes.map(function(cubeRow) { cubeRow.map(HandleOneElement) }) 

pour un tableau de n dimensions de toute forme:

Function.prototype.ArrayFunction = function(param) { 
    if (param instanceof Array) { 
    return param.map(Function.prototype.ArrayFunction, this) ; 
    } 
    else return (this)(param) ; 
} 
HandleOneElement.ArrayFunction(cubes) ; 
0

Ou vous pouvez le faire en alternance avec "foreach()":

var cubes = [ 
[1, 2, 3], 
[4, 5, 6],  
[7, 8, 9], 
]; 

cubes.forEach(function each(item) { 
    if (Array.isArray(item)) { 
    // If is array, continue repeat loop 
    item.forEach(each); 
    } else { 
    console.log(item); 
    } 
}); 

Si vous avez besoin index de tableau, s'il vous plaît essayer ce code:

var i = 0; j = 0; 

cubes.forEach(function each(item) { 
    if (Array.isArray(item)) { 
    // If is array, continue repeat loop 
    item.forEach(each); 
    i++; 
    j = 0; 
    } else { 
    console.log("[" + i + "][" + j + "] = " + item); 
    j++; 
    } 
}); 

Et le résultat ressemblera à ceci:

[0][0] = 1 
[0][1] = 2 
[0][2] = 3 
[1][0] = 4 
[1][1] = 5 
[1][2] = 6 
[2][0] = 7 
[2][1] = 8 
[2][2] = 9 
2

Si vous utilisez ES2015 et que vous voulez définir votre propre objet qui itère comme un tableau 2-D, vous pouvez mettre en œuvre le iterator protocol par:

  1. Définition d'une fonction @@ iterator appelé Symbol.iterator qui retourne ...
  2. ... un objet avec une fonction qui retourne next() ...
  3. ... un objet avec un ou deux propriétés: un value en option avec la valeur suivante (si elle existe) et un booléen done ce qui est vrai si nous avons fini d'itérer.

Une unidimensionnelle fonction iterator tableau ressemblerait à ceci:

// our custom Cubes object which implements the iterable protocol 
function Cubes() { 
    this.cubes = [1, 2, 3, 4]; 
    this.numVals = this.cubes.length; 

    // assign a function to the property Symbol.iterator 
    // which is a special property that the spread operator 
    // and for..of construct both search for 
    this[Symbol.iterator] = function() { // can't take args 

     var index = -1; // keep an internal count of our index 
     var self = this; // access vars/methods in object scope 

     // the @@iterator method must return an object 
     // with a "next()" property, which will be called 
     // implicitly to get the next value 
     return { 
      // next() must return an object with a "done" 
      // (and optionally also a "value") property 
      next: function() { 
       index++; 
       // if there's still some values, return next one 
       if (index < self.numVals) { 
        return { 
         value: self.cubes[index], 
         done: false 
        }; 
       } 
       // else there's no more values left, so we're done 
       // IF YOU FORGET THIS YOU WILL LOOP FOREVER! 
       return {done: true} 
      } 
     }; 
    }; 
} 

Maintenant, nous pouvons traiter notre objet Cubes comme un itérable:

var cube = new Cubes(); // construct our cube object 

// both call Symbol.iterator function implicitly: 
console.log([...cube]); // spread operator 
for (var value of cube) { // for..of construct 
    console.log(value); 
} 

Pour créer le vôtre 2-D itératives, au lieu de retourner une valeur dans notre fonction next(), nous pouvons retourner une autre itérables:

function Cubes() { 
    this.cubes = [ 
     [1, 2, 3, 4], 
     [5, 6, 7, 8], 
     [9, 10, 11, 12], 
    ]; 
    this.numRows = this.cubes.length; 
    this.numCols = this.cubes[0].length; // assumes all rows have same length 

    this[Symbol.iterator] = function() { 
     var row = -1; 
     var self = this; 

     // create a closure that returns an iterator 
     // on the captured row index 
     function createColIterator(currentRow) { 
      var col = -1; 
      var colIterator = {} 
      // column iterator implements iterable protocol 
      colIterator[Symbol.iterator] = function() { 
       return {next: function() { 
        col++; 
        if (col < self.numCols) { 
         // return raw value 
         return { 
          value: self.cubes[currentRow][col], 
          done: false 
         }; 
        } 
        return {done: true}; 
       }}; 
      } 
      return colIterator; 
     } 

     return {next: function() { 
      row++; 
      if (row < self.numRows) { 
       // instead of a value, return another iterator 
       return { 
        value: createColIterator(row), 
        done: false 
       }; 
      } 
      return {done: true} 
     }}; 
    }; 
} 

Maintenant, nous pouvons utiliser l'itération imbriquée:

var cube = new Cubes(); 

// spread operator returns list of iterators, 
// each of which can be spread to get values 
var rows = [...cube]; 
console.log([...rows[0]]); 
console.log([...rows[1]]); 
console.log([...rows[2]]); 

// use map to apply spread operator to each iterable 
console.log([...cube].map(function(iterator) { 
    return [...iterator]; 
})); 

for (var row of cube) { 
    for (var value of row) { 
     console.log(value); 
    } 
} 

Notez que notre coutume itérables ne se comportera pas comme un tableau 2D dans tous les cas; par exemple, nous n'avons pas implémenté une fonction map(). This answer montre comment vous pouvez implémenter une fonction de génération de générateur (see here pour la différence entre les itérateurs et les générateurs, ainsi que les générateurs sont une fonctionnalité ES2016, pas ES2015, donc vous aurez besoin de change your babel presets si vous compilez avec babel).