对于多维javascript数组中的循环

时间:2022-03-29 01:47:39

Since now, I'm using this loop to iterate over the elements of an array, which works fine even if I put objects with various properties inside of it.

从现在开始,我正在使用这个循环迭代数组的元素,即使我在其中放置具有各种属性的对象,它也能正常工作。

var cubes[];

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

Now, let's suppose cubes[] is declared this way

现在,让我们假设cubes []以这种方式声明

var cubes[][];

Can I do this in Javascript? How can I then automatically iterate in

我可以在Javascript中执行此操作吗?然后我怎么能自动迭代

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

As a workaround, I can just declare:

作为解决方法,我可以声明:

var cubes[];
var cubes1[];

and work separately with the two arrays. Is this a better solution?

并与两个数组分开工作。这是更好的解决方案吗?

7 个解决方案

#1


37  

You can do something like this:

你可以这样做:

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

Working jsFiddle:

工作jsFiddle:

The output of the above:

以上输出:

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

#2


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

#3


6  

Try this:

尝试这个:

var i, j;

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

#4


3  

An efficient way to loop over an Array is the built-in array method .map()

循环数组的有效方法是内置数组方法.map()

For a 1-dimensional array it would look like this:

对于一维数组,它看起来像这样:

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

for 2-dimensional array:

对于二维数组:

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

for an n-dimensional array of any form:

对于任何形式的n维数组:

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

#5


2  

If you're using ES2015 and you want to define your own object that iterates like a 2-D array, you can implement the iterator protocol by:

如果您正在使用ES2015并且想要定义自己的迭代类似二维数组的对象,则可以通过以下方式实现迭代器协议:

  1. Defining an @@iterator function called Symbol.iterator which returns...
  2. 定义名为Symbol.iterator的@@迭代器函数,该函数返回...
  3. ...an object with a next() function that returns...
  4. ...具有next()函数的对象返回...
  5. ...an object with one or two properties: an optional value with the next value (if there is one) and a boolean done which is true if we're done iterating.
  6. ...具有一个或两个属性的对象:具有下一个值的可选值(如果有的话)和完成的布尔值如果我们完成迭代则为true。

A one-dimensional array iterator function would look like this:

一维数组迭代器函数如下所示:

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

Now, we can treat our Cubes object like an iterable:

现在,我们可以将Cubes对象视为可迭代:

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

To create our own 2-D iterable, instead of returning a value in our next() function, we can return another iterable:

要创建我们自己的2-D iterable,而不是在next()函数中返回值,我们可以返回另一个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}
        }};
    };
}

Now, we can use nested iteration:

现在,我们可以使用嵌套迭代:

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

Note that our custom iterable won't behave like a 2-D array in all cases; for example, we haven't implemented a map() function. This answer shows how you could implement a generator map function (see here for the difference between iterators and generators; also, generators are an ES2016 feature, not ES2015, so you'll need to change your babel presets if you're compiling with babel).

请注意,我们的自定义iterable在所有情况下都不会像二维数组一样;例如,我们还没有实现map()函数。这个答案显示了如何实现生成器映射函数(请参阅此处了解迭代器和生成器之间的区别;此外,生成器是ES2016的功能,而不是ES2015,因此如果您使用babel编译,则需要更改babel预设)。

#6


1  

JavaScript does not have such declarations. It would be:

JavaScript没有这样的声明。这将是:

var cubes = ...

regardless

而不管

But you can do:

但你可以这样做:

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

  }
}

Note that JavaScript allows jagged arrays, like:

请注意,JavaScript允许锯齿状数组,例如:

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

since arrays can contain any type of object, including an array of arbitrary length.

因为数组可以包含任何类型的对象,包括任意长度的数组。

As noted by MDC:

如MDC所述:

"for..in should not be used to iterate over an Array where index order is important"

“for..in不应该用于迭代索引顺序很重要的数组”

If you use your original syntax, there is no guarantee the elements will be visited in numeric order.

如果您使用原始语法,则无法保证将按数字顺序访问元素。

#7


0  

Or you can do this alternatively with "forEach()":

或者您也可以使用“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);
  }
});

If you need array's index, please try this 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++;
  }
});

And the result will look like this:

结果将如下所示:

[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


37  

You can do something like this:

你可以这样做:

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

Working jsFiddle:

工作jsFiddle:

The output of the above:

以上输出:

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

#2


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

#3


6  

Try this:

尝试这个:

var i, j;

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

#4


3  

An efficient way to loop over an Array is the built-in array method .map()

循环数组的有效方法是内置数组方法.map()

For a 1-dimensional array it would look like this:

对于一维数组,它看起来像这样:

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

for 2-dimensional array:

对于二维数组:

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

for an n-dimensional array of any form:

对于任何形式的n维数组:

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

#5


2  

If you're using ES2015 and you want to define your own object that iterates like a 2-D array, you can implement the iterator protocol by:

如果您正在使用ES2015并且想要定义自己的迭代类似二维数组的对象,则可以通过以下方式实现迭代器协议:

  1. Defining an @@iterator function called Symbol.iterator which returns...
  2. 定义名为Symbol.iterator的@@迭代器函数,该函数返回...
  3. ...an object with a next() function that returns...
  4. ...具有next()函数的对象返回...
  5. ...an object with one or two properties: an optional value with the next value (if there is one) and a boolean done which is true if we're done iterating.
  6. ...具有一个或两个属性的对象:具有下一个值的可选值(如果有的话)和完成的布尔值如果我们完成迭代则为true。

A one-dimensional array iterator function would look like this:

一维数组迭代器函数如下所示:

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

Now, we can treat our Cubes object like an iterable:

现在,我们可以将Cubes对象视为可迭代:

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

To create our own 2-D iterable, instead of returning a value in our next() function, we can return another iterable:

要创建我们自己的2-D iterable,而不是在next()函数中返回值,我们可以返回另一个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}
        }};
    };
}

Now, we can use nested iteration:

现在,我们可以使用嵌套迭代:

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

Note that our custom iterable won't behave like a 2-D array in all cases; for example, we haven't implemented a map() function. This answer shows how you could implement a generator map function (see here for the difference between iterators and generators; also, generators are an ES2016 feature, not ES2015, so you'll need to change your babel presets if you're compiling with babel).

请注意,我们的自定义iterable在所有情况下都不会像二维数组一样;例如,我们还没有实现map()函数。这个答案显示了如何实现生成器映射函数(请参阅此处了解迭代器和生成器之间的区别;此外,生成器是ES2016的功能,而不是ES2015,因此如果您使用babel编译,则需要更改babel预设)。

#6


1  

JavaScript does not have such declarations. It would be:

JavaScript没有这样的声明。这将是:

var cubes = ...

regardless

而不管

But you can do:

但你可以这样做:

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

  }
}

Note that JavaScript allows jagged arrays, like:

请注意,JavaScript允许锯齿状数组,例如:

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

since arrays can contain any type of object, including an array of arbitrary length.

因为数组可以包含任何类型的对象,包括任意长度的数组。

As noted by MDC:

如MDC所述:

"for..in should not be used to iterate over an Array where index order is important"

“for..in不应该用于迭代索引顺序很重要的数组”

If you use your original syntax, there is no guarantee the elements will be visited in numeric order.

如果您使用原始语法,则无法保证将按数字顺序访问元素。

#7


0  

Or you can do this alternatively with "forEach()":

或者您也可以使用“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);
  }
});

If you need array's index, please try this 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++;
  }
});

And the result will look like this:

结果将如下所示:

[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