【问题标题】:How to get nested array length in Javascript?如何在Javascript中获取嵌套数组长度?
【发布时间】:2017-02-14 16:34:11
【问题描述】:

我有一个嵌套数组的例子:

var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];

这是我获取嵌套数组长度的函数:

Array.prototype.getLength = function() {
  var sum = 0;
  function getMultiLength(array) {
    for (count = 0; count < array.length; count ++) {
      sum ++;
      if (!array[count].length) {
        getMultiLength(array[count]);
      }
    }
  }
  getMultiLength(this.valueOf());
  return sum;
};

我对结果的期望是 12,但我得到的是无限循环:

testArray.getLength(); //infinite loop

有人知道为什么以及如何获取嵌套数组长度吗?

【问题讨论】:

    标签: javascript arrays function multidimensional-array infinite-loop


    【解决方案1】:

    你好,这里的答案是使用 Array.isArray 来识别它是否是数组,然后调用函数再做一次,依此类推。

    let test = [1, [2, [3, [4, [5, 6],7,[8,9,10,[11,12]]]]]];
    let length = 0;
    function len(array){
       for(let i in array){
          if(Array.isArray(array[i])){
              len(array[i])
           }else{
              length++
           }
        }
        return length;
    };
    
    len(test)
    console.log(length)
    

    【讨论】:

      【解决方案2】:
      [].concat.apply([[]], testArray).length
      

      有关申请的信息,请参阅:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

      【讨论】:

      • 这不适用于[].concat.apply([[]],[[1],[2]]).length
      • 另一个问题
      • 我后来意识到,但实际上编辑你的答案给了我解决我在上面评论中提到的问题的解决方案,解决方案是[].concat.apply([], testArray).length
      【解决方案3】:

      以上所有答案都有帮助,只是添加另一个简单的答案。希望它对将来的某人有用。

      const getLength = arr => arr.flat(Infinity).length;
      
      var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
      console.log(getLength(testArray));

      我们在这里使用flat() 方法将数组展平为单个数组,然后计算它的长度。请注意,我们将深度传递为Infinity,因为我们想一直深入并计算整个长度。

      flat() 方法创建一个包含所有子数组元素的新数组 递归地连接到它,直到指定的深度。在我们的 如果我们将深度定义为无穷大

      阅读更多flat()

      【讨论】:

        【解决方案4】:

        您的代码有问题

        您现有的代码失败,因为递归检查是向后的。如果长度为非零,您希望递归。所以应该是

          if (array[count].length) getMultiLength(array[count]);
          else sum++;
        

        就您的代码而言,即使array[count] 不是 数组,getMultiLength 也会被调用(因为如果array[count] 不是数组,length 将未定义)。所以它会一直循环下去。只需在调试器中单步执行您的代码,就可以很容易地弄清楚这一点。

        顺便说一句,你不需要this.valueOf()。在这种情况下,这与this 相同。

        调整您的代码

        但实际上,您可以通过消除不必要的内部函数并使用递归调用的返回值来简化代码:

        Array.prototype.getLength = function() {
          let sum = 0;
          for (let count = 0; count < this.length; count ++) {
            sum += this[count].length ? this[count].getLength() : 1;
          }
          return sum;
        };
        

        有些人可能更喜欢使用reduce

        Array.prototype.getLength = function() {
          return this.reduce((sum, elt) => 
            sum + (elt.length ? elt.getLength() : 1), 0);
        };
        

        另一种使用扁平化的解决方案

        另一种解决方案是展平数组,然后找到展平数组的长度。这里我们使用generator 来创建一个真正易于阅读和理解的扁平化器(ES6 特性):

        function *flatten(array) {
          for (elt of array) 
            if (Array.isArray(elt)) yield *flatten(elt);
            else yield elt;
        }
        
        var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
        
        console.log(Array.from(flatten(testArray)).length);

        flatten 的替代实现

        或者,使用您自己喜欢的flatten 实现,例如这个递归版本:

        function flatten(value) {
          return Array.isArray(value) ? [].concat(...value.map(flatten)) ? value;
        }
        

        或在 ES5 中

        function flatten(value) {
          return Object.prototype.toString.call(value) === '[object Array]' ?
            [].concat.apply([], value.map(flatten)) :
            value;
        }
        

        把它放在Array原型上

        如果你坚持把这个放在原型上,那么

        Object.defineProperty(Array.prototype, 'getLength', {
          value() { return flatten(this).length; }
        });
        

        使用defineProperty 使该属性不可枚举、不可配置等。

        【讨论】:

          【解决方案5】:

          我想贡献的两种方法;

          递归:

          var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
                   flat = a => a.reduce((p,c) => p.concat(Array.isArray(c) ? flat(c) : c),[]);
                 result = flat(testArray).length;
          console.log(result);

          游击队:

          var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
                 result = JSON.stringify(testArray).match(/,/g).length+1;
          console.log(result);

          【讨论】:

            【解决方案6】:

            我使用递归调用来查找嵌套数组长度

            var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
            
            var totalLen=0;
            function length(arr){
            
               for(var ele in arr){
                 if(Array.isArray(arr[ele])){
                   length(arr[ele])
                 }else{
                     totalLen++;
                 }
               }
            
            }
            
            length(testArray);
            console.log(totalLen); //o/p 12
            

            这里临时不使用全局变量

            var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
            
            
            var ArrayUtils=function(){
            
                  var totalLength=0;
            
                  function getNestedArrayLength(arr){
            
                     for(var ele in arr){
            
                         if(Array.isArray(arr[ele])){
                           getNestedArrayLength(arr[ele])
                         }else{
                             totalLength++;
                         }
                       }
                  }
            
                  function getLength(arr){
            
                        getNestedArrayLength(arr);
                        return totalLength;
            
                  }
            
                  return {
                      getLength:getLength
                  }
            }
            
            var aU=new ArrayUtils();
            var length=aU.getLength(testArray);
            
            console.log(length); //Op 12
            

            【讨论】:

            • 你能不能试着用一种不使用全局变量的方式来写这个,并且将长度作为函数的值返回?
            • @torazaburo,你能检查一下吗?上面的代码我试过没有全局变量
            【解决方案7】:

            嵌套数组有一个递归调用来计算它们的非数组项:

            var testArray = [1, 2, [3, 4, [5, 6], 7], 8, 9, [10, 11], 12];
            
            Array.prototype.getLength = function () {
                function getMultiLength(array) {
                    var sum = 0;
                    for (var count = 0; count < array.length; count++) {
                        if (Array.isArray(array[count])) {
                            sum += getMultiLength(array[count]);
                        } else {
                            sum++;
                        }
                    }
                    return sum;
                }
            
                return getMultiLength(this.valueOf());
            };
            
            alert(testArray.getLength());

            【讨论】:

              【解决方案8】:

              试试这个:

              <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
              var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
              var s = 1;
              $.each(testArray, function(index, value){
                  s = s + $(this).length; 
              });
              console.log(s);
              

              【讨论】:

              • 答案不应依赖于未在问题中标记或在代码中指示的库。至少它应该解释它需要的库。
              • 没有理由只为each 拖入 jQuery -- 使用 ES6 方法并指向 pollyfill
              • @JeremyJStarcher 我同意,但你指的是哪种 ES6 方法?
              【解决方案9】:

              试试这个:

              Array.prototype.getLength = function() {
                var sum = 0;
                function getMultiLength(array) {
                  for (var count = 0; count < array.length; count ++) {
                    sum ++;
                    if (array[count].length) {
                      getMultiLength(array[count]);
                    }
                  }
                }
                getMultiLength(this.valueOf());
                return sum;
              };
              
              var testArray = [1,2,[3,4,[5,6],7],8,9,[10,11],12];
              
              testArray.getLength()
              
              1. 不要使用 GLOBAL 变量计数。
              2. 如果数组为空,为什么要对数组进行计数?

              【讨论】:

              • 答案应该解释 OPs 问题以及如何解决它。仅代码的答案并不是特别有用。您是否尝试过使用元素为字符串的数组?
              • 不要给鱼,是吗?请看答案下面提到的几点。
              猜你喜欢
              • 2015-03-24
              • 2019-04-09
              • 2019-05-02
              • 1970-01-01
              • 2013-10-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-20
              相关资源
              最近更新 更多