对于多维javascript数组中的循环

时间:2012-04-05 02:22:11

标签: javascript loops multidimensional-array

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

var cubes[];

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

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

var cubes[][];

我可以在 Javascript 中执行此操作吗?我怎样才能自动迭代

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

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

var cubes[];
var cubes1[];

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

8 个答案:

答案 0 :(得分:46)

您可以这样做:

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:

以上的输出:

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

答案 1 :(得分:13)

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

答案 2 :(得分:6)

循环数组的有效方法是built-in array method .map()

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

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

用于二维数组:

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

表示任何形式的n维数组:

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

答案 3 :(得分:5)

试试这个:

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)

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

  1. 定义名为Symbol.iterator @@ iterator 函数,该函数返回...
  2. ...具有next()函数的对象返回...
  3. ...具有一个或两个属性的对象:具有下一个值(如果有)的可选value和一个布尔done如果我们已经完成迭代则为真
  4. 一维数组迭代器函数如下所示:

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

    现在,我们可以将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);
    }
    

    要创建我们自己的 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}
            }};
        };
    }
    

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

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

    请注意,我们的自定义迭代在所有情况下都不会像二维数组一样;例如,我们还没有实现map()功能。 This answer展示了如何为迭代器和生成器之间的差异实现生成器映射函数(see here;同时,生成器是ES2016的特性,而不是ES2015,因此您需要{{3如果你正在用babel进行编译)。

答案 5 :(得分:3)

为时已晚,但是此解决方案又好又整洁

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

或者您的情况:

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
}

注意: for ... of循环在ES6中是标准化的,因此只有在具有ES5 Javascript编译器(例如Babel)的情况下才使用此循环

另一个说明:还有其他选择,但是它们有一些细微的差异和行为,例如forEach()for...infor...of和传统的{{1 }}。取决于您的情况来决定使用哪个。 (ES6还具有for().map().filter().find()

答案 6 :(得分:1)

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

var cubes = ...

无论

但你可以这样做:

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

  }
}

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

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

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

正如MDC所述:

  

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

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

答案 7 :(得分:1)

或者您也可以使用&#34; forEach()&#34;

来执行此操作
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);
  }
});

如果您需要数组索引,请尝试以下代码:

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

结果将如下所示:

[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