How to get nested array length in Javascript?

烂漫一生 提交于 2019-12-06 13:33:53

问题


I have an example of nested array:

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

Here is my function for getting nested array length:

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

My expectation for result would be 12, but instead what I got is infinite loop:

testArray.getLength(); //infinite loop

Anyone know why and how to get nested array length?


回答1:


Problem with your code

Your existing code fails because the check for recursing is backward. You want to recurse if the length is non-zero. So it should be

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

As your code stands, getMultiLength will be called even if array[count] is not an array (because if array[count] is not an array, length will be undefined). So it will keep recursing forever. This would be pretty easy to figure out by just stepping through your code in the debugger.

By the way, you don't need this.valueOf(). That is the same as this in this case.

Tweaking your code

But actually, you could streamline your code by eliminating the unnecessary inner function, and using the return value of the recursive calls:

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

Some people might prefer to write this using reduce:

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

Another solution using flattening

An alternative solution is to flatten the array, then find the length of the flattened array. Here we use a generator to create a flattener which is real easy to read and understand (ES6 feature):

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

Alternative implementation of flatten

Or, use your own favorite implementation of flatten, such as this recursive version:

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

or in ES5

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

Putting it on the Array prototype

If you insist on putting this on the prototype, then

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

Use defineProperty to make this property non-enumerable, non-configurable etc.




回答2:


Try this :

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



回答3:


There is a recursion call for nested arrays to count their non-array items:

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



回答4:


I used recursive call to find nested array length

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

Improvised not using global variable here

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



回答5:


Two methods that i would like to contribute with;

Recursive:

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

Guerilla:

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:


Try this:

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. Do not use GLOBAL variable count.
  2. Why do you want to count array if it is empty?


来源:https://stackoverflow.com/questions/39887381/how-to-get-nested-array-length-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!