Taylor Kay
Taylor Kay

Reputation: 59

Get the length of properties in a multidimensional array based on dimension?

Using vanilla JavaScript, I want to access the length of a multidimensional array based on the "dimension" it is in.

Example:

Here's a multidimensional array

  var myArray = [a, b, c, d, [e, [f], g]]

Dimension 0 in has 5 elements [a, b, c, d, [e, [f], g]]

Dimension 1 has 3 elements [e, [f], g]

Dimension 2 has 1 element [f]

This is what I have so far (which isn't a lot to go off of - I'm really stuck)

var getLength = function(arr, dimension) {
  subarray = [];
  for (var e in arr) {
    if (e instanceof Array) {  
     return e.length
    }
  }
}

// getLength(myArray, 2) should equal 1

Can you kindly help?

Upvotes: 2

Views: 333

Answers (2)

CJVic
CJVic

Reputation: 11

You can have a helper method get the count of members recursively, then use the main method to just access which layer count is wanted using "layer":

Pseudocode for helper function:

// Count members, and store if object
// Recursively get list of lengths from those objects
// Sum up those lists
    // find length of longest array
    // sum up all values, up to length of longest array
// Insert 'count' at front of the list
// Return

Full code:

/*
Main function
Returns a number: the count of members in a layer
*/
function getLength(layer, obj)
{
    return getAllLengths(obj)[layer];
}



/*
Helper function for getLength(..)
Returns an array
*/
function getAllLengths(obj)
{
    var count = 0; // for this layer's # of members
    var objectMembers = []; // list of members that are objects
    var objectsLists = []; // to store list of lists produced recursively from objectMembers
    var result = []; // to return


    // count, and store if object
    for (var mem in obj)
    {
        count++;
        if (obj[mem] instanceof Object)
        {
            objectMembers.push(obj[mem] );
        }
    }


    // recursively get objects' lists
    for (var i in objectMembers)
    {
        objectsLists.push(getAllLengths(objectMembers[i] ));
    }


    ////// sum up lists
    // find length of longest array
    var maxLength = 0;
    for (var i in objectsLists)
    {
        if (objectsLists[i].length > maxLength)
        {
            maxLength = objectsLists[i].length;
        }
    }
    // sum
    for (var i = 0; i < maxLength; i++)
    {
        var sum = 0;
        for (var j = 0; j < objectsLists.length; j++)
        {
            if (objectsLists[j][i] != undefined)
                sum += objectsLists[j][i];
        }
        result.push(sum);
    }


    // complete resulting list to return
    result.splice(0,0, count);

    return result;
}

Upvotes: 1

elclanrs
elclanrs

Reputation: 94131

You could reduce and recurse while keeping track of arrays that have been seen:

var depthCount = function(xss, depth) {
  depth = depth || 0
  var seen = []
  return xss.reduce(function(acc, xs) {
    if (Array.isArray(xs)) {
      return acc.concat(depthCount(xs, depth + 1))
    }
    if (seen.indexOf(xss) < 0) {
      seen.push(xss)
      return acc.concat({depth: depth, count: xss.length})
    }
    return acc
  }, [])
}

var xs = [1, 2, 3, 4, [5, [6], 7]]

console.log(depthCount(xs))
// [{depth: 0, count: 5},
//  {depth: 1, count: 3},
//  {depth: 2, count: 1}]

Then you can find out the total by filtering the collection by depth and checking the count. If you sum up the counts it will work when you have multiple arrays of the same depth too:

var xs = [1, [2, 3], [4, 5, [6, 7]]]

var count = depthCount(xs)

console.log(count)
// [{depth: 0, count: 3},
//  {depth: 1, count: 2},
//  {depth: 1, count: 3},
//  {depth: 2, count: 2}]

var countTotalDepth = function(depth, coll) {
  return coll.filter(function(obj) {
    return obj.depth === depth
  }).reduce(function(x, y) {
    return x.count + y.count
  })
}

console.log(countTotalDepth(1, count)) // 5

Upvotes: 1

Related Questions