【问题标题】:For loop in multidimensional javascript array多维javascript数组中的for循环
【发布时间】:2012-04-18 19:03:48
【问题描述】:

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

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[];

并分别使用这两个数组。这是更好的解决方案吗?

【问题讨论】:

    标签: javascript loops multidimensional-array


    【解决方案1】:

    你可以这样做:

    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
    

    【讨论】:

    • 您的解决方案仅适用于 2D 数组,但我找到了一种循环遍历任意维数数组的方法:stackoverflow.com/a/15854485/975097
    • @AndersonGreen OP 专门寻找二维数组,因此得到了上述答案。不过感谢您提供的链接 - 希望它对将来寻找类似解决方案的人有所帮助!
    • @Bharadwaj 这是一个全新的问题 - 看看这个:stackoverflow.com/questions/4331092/…
    • 谢谢@icyrock.com。它帮助了我。
    【解决方案2】:
    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]);
        }
    }
    

    【讨论】:

    • 然后他问“我可以用 javascript 做这个吗?”
    • 您在我发表评论后编辑了您的答案。您的原始帖子与迭代无关。
    【解决方案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 和传统的for()。这取决于您的情况来决定使用哪一个。 (ES6还有.map().filter().find().reduce()

    【讨论】:

      【解决方案4】:

      循环遍历数组的一种有效方法是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) ;
      

      【讨论】:

        【解决方案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];
            }
        }
        

        【讨论】:

        • 这将创建全局变量。
        • 添加了 var i, j;公平地说,他没有说“不要创建全局变量”。 ;-)
        • 为什么要在新行上声明 i 和 j 而你可以在循环中这样做? for(var i = 0; ...)
        【解决方案6】:

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

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

        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
        

        【讨论】:

          【解决方案7】:

          如果您使用的是 ES2015,并且想要定义自己的对象,该对象像二维数组一样进行迭代,您可以通过以下方式实现 iterator protocol

          1. 定义一个名为Symbol.iterator@@iterator 函数,它返回...
          2. ...带有next() 函数的对象返回...
          3. ...一个具有一个或两个属性的对象:一个可选的value 具有下一个值(如果有的话)和一个布尔值done,如果我们完成了迭代,则为真。

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

          // 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 可迭代对象,我们可以返回另一个可迭代对象,而不是在 next() 函数中返回值:

          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,因此如果您正在编译,则需要 change your babel presets通天塔)。

          【讨论】:

            【解决方案8】:

            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 不应该用于遍历索引顺序的数组 很重要”

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-11-21
              • 2021-02-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-02-07
              • 2015-11-24
              相关资源
              最近更新 更多