web-dev-qa-db-fra.com

Pour la boucle dans un tableau javascript multidimensionnel

Depuis lors, j'utilise cette boucle pour parcourir les éléments d'un tableau, ce qui fonctionne bien même si je place des objets avec différentes propriétés à l'intérieur.

var cubes[];

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

Supposons maintenant que les cubes [] soient déclarés de cette façon

var cubes[][];

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

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

En guise de solution de contournement, je peux simplement déclarer:

var cubes[];
var cubes1[];

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

25
Saturnix

Vous pouvez faire quelque chose comme ça:

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

JsFiddle de travail:

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
41
icyrock.com
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]);
    }
}
12
binarious

Une méthode efficace pour boucler sur un tableau est la méthode intégrée du tableau .map ()

Pour un tableau à 1 dimension, cela ressemblerait à ceci:

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

pour un tableau à 2 dimensions:

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

pour un tableau à n dimensions de n'importe quelle forme:

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

Essaye ça:

var i, j;

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

Si vous utilisez ES2015 et que vous souhaitez définir votre propre objet qui itère comme un tableau 2D, vous pouvez implémenter le protocole itérateur de:

  1. Définir une fonction @@ iterator appelée Symbol.iterator qui renvoie ...
  2. ... un objet avec une fonction next() qui renvoie ...
  3. ... un objet avec une ou deux propriétés: une value optionnelle avec la valeur suivante (s'il en existe une) et une valeur booléenne done qui est vraie si nous avons terminé l'itération.

Une fonction d'itérateur de tableau unidimensionnelle 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 notre propre 2-D iterable, au lieu de retourner une valeur dans notre fonction next(), nous pouvons retourner un autre iterable:

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 custom iterable ne se comportera pas comme un tableau 2D dans tous les cas. Par exemple, nous n'avons pas implémenté de fonction map(). Cette réponse montre comment vous pouvez implémenter une fonction de carte de générateur ( voir ici pour la différence entre les itérateurs et les générateurs; de plus, les générateurs sont une fonctionnalité ES2016, pas ES2015, vous aurez donc besoin pour changer vos préréglages babel si vous compilez avec babel).

2
Galen Long

Un peu trop tard, mais cette solution est belle et soignée

const arr = [[1,2,3],[4,5,6],[7,8,9,10]]
for (let i of arr) {
  for (let j of i) {
    console.log(j) //Should log numbers from 1 to 10
  }
}

Ou dans votre cas:

const arr = [[1,2,3],[4,5,6],[7,8,9]]
for (let [d1, d2, d3] of arr) {
  console.log(`${d1}, ${d2}, ${d3}`) //Should return numbers from 1 to 9
}

Remarque: La bouclefor ... of est normalisée dans ES6. Ne l'utilisez donc que si vous avez un Complément Javascript ES5 (tel que Babel).

Autre remarque: Il existe des alternatives, mais elles présentent quelques différences et comportements subtils, tels que forEach(), for...in, for...of et le for() traditionnel. Cela dépend de votre cas pour décider lequel utiliser. (ES6 a également .map(), .filter(), .find(), .reduce())

2
WebDeg Brian

Ou vous pouvez le faire alternativement 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 de l'index d'un tableau, essayez 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
1
Masa S-AiYa

JavaScript n'a pas de telles déclarations. Ce serait:

var cubes = ...

indépendamment

Mais vous pouvez faire:

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

  }
}

Notez que JavaScript autorise les tableaux déchiquetés, tels que:

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

puisque les tableaux peuvent contenir n’importe quel type d’objet, y compris un tableau de longueur arbitraire.

Comme indiqué par MDC :

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

Si vous utilisez votre syntaxe d'origine, rien ne garantit que les éléments seront visités dans l'ordre numérique.

1
Matthew Flaschen