【问题标题】:Why this doesn't work on array numbers?为什么这不适用于数组编号?
【发布时间】:2018-03-01 14:10:37
【问题描述】:

我正在玩数组只是学习 javascript 基础知识,每当我将传递的参数更改为一个数字时,我都会在这里得到一个基本函数 console.log(arr[i][j][k]) 给我未定义,但如果它是一个字符串,它会记录数字。

function array(arr) {
    for(var i=0;i < arr.length;i++){
      for(var j=0; j < arr[i].length; j++){
            for(var k=0; k < arr[i][j].length; k++){
              console.log(arr[i][j][k])
            }
      }
    }
}

array(['1','2',['3','4'],['5','6','7']]); // change to a number and will give undefined.

【问题讨论】:

    标签: javascript arrays loops multidimensional-array


    【解决方案1】:

    问题是因为您在循环中调用.length。数字没有.length 方法,因此它返回未定义。然而,字符串确实有这种方法。

    作为可行的示例,您可以检查数组中的索引是否为数字,然后检查 console.logcontinue(数组中的下一个索引)。

    function array(arr) {
      for(var i=0;i < arr.length;i++){
        for(var j=0; j < arr[i].length; j++){    
          if (typeof arr[i][j] === 'number') {
            console.log(arr[i][j]);
            continue;
          }
          
          for(var k=0; k < arr[i][j].length; k++){
            console.log(arr[i][j][k])
          }
        }
      }
    }
    
    array(['1','2',['3','4'],['5','6', 7]]);

    您需要在每个循环中执行此检查,以说明数组中任何位置的数字。

    以@chazsolo 的回答为基础,这是一种非 ES6 做同样事情的方法,以防万一将 ES6 语法混入其中会造成混乱

    var allItems = function (array) {
      var i = 0;
      // Loop through all items
      for (i; i < array.length; ++i) {
        // If this item is an array
        // You could also use typeof or Array.isArray as below
        if (toString.call(array[i]) === '[object Array]') {
          allItems(array[i]); // run this function again with this array
          continue; // move to next item
        }
        
        console.log(array[i]);
      }
    }
    
    allItems([1, 2, [3, 4], [5, 6, 7]]);
    
    allItems(['1', '2', ['3', '4'], ['5', '6', '7']]);
    
    allItems(['a', ['b', ['c', ['d', ['e', ['f', ['g']]]]]]]);

    首先,我们遍历数组中的所有项目。我们检查项目本身是否是一个数组(我在这里调用toString,如果它是一个数组则返回[object Array])。如果它是一个数组,那么我们对这个数组运行相同的函数(递归),然后跳到下一项,因为我们不需要对这个数组做任何其他事情。

    如果它不是一个数组,那么我们可以通过控制台记录它(这里我们假设它是一个数字或字符串,注意混入的对象)。

    【讨论】:

      【解决方案2】:

      以@CarlMarkham 的回答为基础,这解释了为什么您不应该在数组的每个项目上调用.length(您没有进行类型检查,因此对于数字未定义.length)。

      令人不满意的是,您将自己限制在 3 级嵌套数组中。这是递归如何帮助使其更加灵活的一个很好的例子。使用 ES6 考虑以下内容:

      const allItems = (array) => {
        for (let i of array) {
          Array.isArray(i) ? allItems(i) : console.log(i);
        }
      }
      
      allItems([1, 2, [3, 4], [5, 6, 7]]);
      
      allItems(['1', '2', ['3', '4'], ['5', '6', '7']]);
      
      allItems(['a', ['b', ['c', ['d', ['e', ['f', ['g']]]]]]]);

      【讨论】:

      • 在哪里可以找到您在这里使用的方法?
      • 网上有很多资源,但您可以先查看 MDN 在 recursionfor...ofES6 support 上的文档
      【解决方案3】:

      请注意,上述两种解决方案使用递归函数,这意味着函数会一遍又一遍地调用自身,直到满足“基本情况”。在这些情况下,它们在自身内部调用函数 allItems()。

      这指出了对复杂数据结构使用递归函数的优势。也就是说,无论您的数据结构有多复杂,无论它有多嵌套,无论您是否知道有多少维,递归函数都可以根据需要多次执行函数或操作。

      因此,如果您知道您的数据结构是双嵌套的,那么循环是一个很好的解决方案,因为您知道需要多少次循环才能访问这些维度内的所有元素。

      但是,如果您有一个非常多维的数据结构,其中包含许多您可能不知道的嵌套结构和元素,您将不知道要使用多少个循环,并且递归函数会处理这种复杂性基于您的有条件的“基本案例”。正如有人之前所说,递归会在执行每个循环之前检查一个条件,这与标准循环不同。

      希望在以后处理复杂的数据结构时对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-22
        • 1970-01-01
        • 2017-04-24
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多