Reputation: 59
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
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
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