objects - Para bucle en matriz javascript multidimensional
find object in array javascript (8)
Desde ahora, estoy usando este bucle para recorrer en iteración los elementos de una matriz, que funciona bien incluso si pongo objetos con varias propiedades dentro de ella.
var cubes[];
for (i in cubes){
cubes[i].dimension
cubes[i].position_x
ecc..
}
Ahora, supongamos que los cubos [] se declaran de esta manera
var cubes[][];
¿Puedo hacer esto en Javascript ? ¿Cómo puedo entonces iterar automáticamente en
cubes[0][0]
cubes[0][1]
cubes[0][2]
cubes[1][0]
cubes[1][1]
cubes[1][2]
cubes[2][0]
ecc...
Como solución, puedo declarar:
var cubes[];
var cubes1[];
y trabajar por separado con las dos matrices. ¿Es esta una mejor solución?
JavaScript no tiene tales declaraciones. Podría ser:
var cubes = ...
sin importar
Pero puedes hacer:
for(var i = 0; i < cubes.length; i++)
{
for(var j = 0; j < cubes[i].length; j++)
{
}
}
Tenga en cuenta que JavaScript permite matrices irregulares, como:
[
[1, 2, 3],
[1, 2, 3, 4]
]
ya que las matrices pueden contener cualquier tipo de objeto, incluida una matriz de longitud arbitraria.
Como lo señaló el MDC :
"for..in no debe usarse para iterar sobre una matriz donde el orden del índice es importante"
Si utiliza su sintaxis original, no hay garantía de que los elementos se visitarán en orden numérico.
O puede hacer esto alternativamente con "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 necesita un índice de matriz, pruebe este código:
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++;
}
});
Y el resultado se verá así:
[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
Prueba esto:
var i, j;
for (i = 0; i < cubes.length; i++) {
for (j = 0; j < cubes[i].length; j++) {
do whatever with cubes[i][j];
}
}
Puedes hacer algo como esto:
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]);
}
}
Trabajando jsFiddle:
La salida de lo anterior:
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
Si está utilizando ES2015 y desea definir su propio objeto que se repita como una matriz bidimensional, puede implementar el protocolo de iterador de la siguiente manera:
- Definiendo una función @@
Symbol.iterator
llamadaSymbol.iterator
que devuelve ... - ... un objeto con una función
next()
que devuelve ... - ... un objeto con una o dos propiedades: un
value
opcional con el siguiente valor (si hay uno) y un valor booleanodone
que es verdadero si hemos terminado de iterar.
Una función de iterador de matriz unidimensional se vería así:
// 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}
}
};
};
}
Ahora, podemos tratar nuestro objeto Cubes
como un iterable:
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);
}
Para crear nuestro propio iterable en 2-D , en lugar de devolver un valor en nuestra función next()
, podemos devolver otro 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}
}};
};
}
Ahora, podemos usar iteración anidada:
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);
}
}
Tenga en cuenta que nuestro iterable personalizado no se comportará como una matriz 2-D en todos los casos; por ejemplo, no hemos implementado una función map()
. Esta respuesta muestra cómo podría implementar una función de mapa del generador ( vea aquí la diferencia entre los iteradores y los generadores; también, los generadores son una función de ES2016, no de ES2015, por lo que deberá cambiar sus ajustes predeterminados de babel si está compilando con babel ).
Un poco demasiado tarde, pero esta solución es agradable y limpia
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
}
}
O en tu caso:
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
}
Nota: for ... of
loop está estandarizado en ES6, así que solo use esto si tiene un ES5 Javascript Complier (como Babel)
Otra nota: hay alternativas, pero tienen algunas diferencias sutiles y comportamientos, como forEach()
, for...in
, for...of
y traditional for()
. Depende de su caso para decidir cuál usar. (ES6 también tiene .map()
, .filter()
, .find()
, .reduce()
)
Una forma eficiente de realizar un bucle en una matriz es el método de matriz integrado .map ()
Para una matriz unidimensional se vería así:
function HandleOneElement( Cuby ) {
Cuby.dimension
Cuby.position_x
...
}
cubes.map(HandleOneElement) ; // the map function will pass each element
para matriz bidimensional:
cubes.map( function( cubeRow ) { cubeRow.map( HandleOneElement ) } )
Para una matriz n-dimensional de cualquier forma:
Function.prototype.ArrayFunction = function(param) {
if (param instanceof Array) {
return param.map( Function.prototype.ArrayFunction, this ) ;
}
else return (this)(param) ;
}
HandleOneElement.ArrayFunction(cubes) ;
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]);
}
}