8

Often, there are situations where I need to determine whether a Javascript array is rectangular (and get the dimensions of the array). In this case, I mean determining whether every element of the array is an array with the same length. How can I do this?

function getArrayDimensions(theArray){
    //if the array's dimensions are 3x3, return [3, 3], and do the same for arrays of any dimension
    //if the array is not rectangular, return false
}

Additionally, how can this function be generalized to multidimensional arrays (2x5x7, 3x7x8x8, etc.)?

10
  • It would be useful to generalize this concept for arrays of any dimension (not just two dimensions) and find the dimensions of the array. Commented Dec 11, 2012 at 6:11
  • Just check the length of the array and then check the length of one of the sub-elements. If they're not equal, it's defintely rectangular. Commented Dec 11, 2012 at 6:12
  • @Jack rectangular is not necessary a square, and this is not what the OP is asking. Commented Dec 11, 2012 at 6:14
  • @VaughanHilts I need to generalize this to arrays of any dimension, though - I think that would involve the use of recursion. Commented Dec 11, 2012 at 6:14
  • 1
    @AndersonGreen Well, fwiw, I've updated my answer yet again; it's probably as short as it will ever get :) I've also voted to reopen the question, because the linked duplicate has no definitive answers. Commented Dec 13, 2012 at 5:56

7 Answers 7

11

This recursive function returns all dimensions of a given array or false if one or more dimensions are not straight (i.e. different sizes between array items). It uses a helper function to determine whether two simple arrays are the same (read the function comments before using it).

// pre: a !== b, each item is a scalar
function array_equals(a, b)
{
  return a.length === b.length && a.every(function(value, index) {
    return value === b[index];
  });
};

function getdim(arr)
{
  if (/*!(arr instanceof Array) || */!arr.length) {
    return []; // current array has no dimension
  }
  var dim = arr.reduce(function(result, current) {
    // check each element of arr against the first element
    // to make sure it has the same dimensions
    return array_equals(result, getdim(current)) ? result : false;
  }, getdim(arr[0]));

  // dim is either false or an array
  return dim && [arr.length].concat(dim);
}

console.log(getdim(123)); // []
console.log(getdim([1])); // [1]
console.log(getdim([1, 2])); // [2]
console.log(getdim([1, [2]])); // false
console.log(getdim([[1, 2], [3]])); // false
console.log(getdim([[1, 2],[1, 2]])); // [2, 2]
console.log(getdim([[1, 2],[1, 2],[1, 2]])); // [3, 2]

console.log(getdim([[[1, 2, 3],[1, 2, 4]],[[2, 1, 3],[4, 4, 6]]])); // [2, 2, 3]

console.log(getdim([[[1, 2, 3], [1, 2, 4]], [[2, 1], [4, 4]]])); // false

Sign up to request clarification or add additional context in comments.

10 Comments

Also I've explicitly checked the parameter is an array, because the length property could be anything, not necessary an array (e.g. [{length:100},{length:200}] and this code screws up)
@AndersonGreen Updated for rectangular dimensions.
@AlvinWong Thanks for the feedback. I suppose the conditions should be strengthened if objects may occur; I've added it as a code comment though.
@AlvinWong Fixed now; I calculate the dimensions of the first item and compare that against subsequent elements, shifting off the dimension in each recursion call :)
You finally decided that you cannot omit the part of comparing two arrays :P
|
2

Here is a simple recursive function to do that. Wrote it very quickly, so may prone to errors.

This function returns the lengths of each dimensions. If it contains sub-arrays of different lengths, this function returns false.

This function works for different dimensions.

For example, passing a 2d array of 2x3 will return [2, 3], a 3d array of 2x3x4 will return [2, 3, 4]. The dimension (i.e. n d) can be obtained by checking the length of the returned array.

// Array dimension checker
// Returns:
//   false when array dimensions are different
//   an Array when is rectangular 0d (i.e. an object) or >=1d
function arrayDimension(a) {
    // Make sure it is an array
    if (a instanceof Array) {
        // First element is an array
        var sublength = arrayDimension(a[0]);
        if (sublength === false) {
            // Dimension is different
            return false;
        } else {
            // Compare every element to make sure they are of the same dimensions
            for (var i = 1; i < a.length; i++) {
                var _sublength = arrayDimension(a[i]);
                // HACK: compare arrays...
                if (_sublength === false || sublength.join(",") != _sublength.join(",")) {
                    // If the dimension is different (i.e. not rectangular)
                    return false;
                }
            }
            // OK now it is "rectangular" (could you call 3d "rectangular"?)
            return [a.length].concat(sublength);
        }
    } else {
        // Not an array
        return [];
    }
}

Demo (Check the javaScript console :) )

4 Comments

Does this apply to arrays of any dimension, or does it only apply to two-dimensional arrays?
@AndersonGreen In my demo I have a 3d array, which shows that it should work for more dimensions. You can make a 4d and try.
It appears that this function returns the maximum depth at which every element has the same length. The function's output is correct for all the multidimensional arrays that I've tested so far.
@AndersonGreen I've modified the code. Please check. This has different behaviour than the previous one. Also beware of Jack's answer. See my comments there.
1

How about using Array.every.

Example:

var firstLen = ar[0].length;

var isRectangular = ar.every(function(item) {
return item.length == firstLen;
}

5 Comments

Where is the relevant documentation for Array.every?
Also, would this work for 3- or 4- dimensional arrays (and not just two-dimensional arrays?)
This works only for ECMAScript 5 browsers that is IE9 and others. The documentation above gives sample code for how to write every function for old browsers.
@AndersonGreen If you want to test more than two dimensions you have to add that to your question and not as an afterthought comment.
1
function isRectangular(arr){
    for(x in arr){
        if(arr[x+1].length != arr[x].length)
            return false;
    }
    return true;
}

And for more dimensions:

function isPrismatic(arr){
    for(x in arr){
        if(typeof arr[x] == "object" && arr[x+1].length == arr[x].length)
            return isPrismatic(arr[x]);
        else if(arr[x].length != arr[x+1].length)
            return false;
    } return true;
}

3 Comments

How can this function be generalized so that it will work for arrays of any dimension (e.g., 3x4x6, 3x3x9, 6x6x1)? (If it were generalized in this way, it would return true if every sub-array had the same length, and every sub-sub-array had the same length.)
It is inappropriate to use for..in here as you will not know the first array's length, e.g. [[1,2],,[1,2]] will return true when it should probably be false. Use a plain for loop for both loops and test that lengths are equal.
null are type object too, OP might want to exclude them depending if this is important to him or not
1

The simple implementation is to check that all the internal arrays have the same length as the outer array:

function isSquare(arr) {
  var len = arr.length;

  for (var i=0; i<len; i++) {

    if (arr[i].length != len) {
      return false;
    }
  }
  return true;
}

so:

isSquare([[1,2],[3,4]]);   // true
isSquare([[1,2],[3,4,5]]); // false

Edit

If you want "rectangular" arrays where each of the member arrays are the same length but not necessarily the same length as the outer array:

function isRectangleArray(arr) {
  var len = arr[0].length;

  for (var i=0, iLen=arr.length; i<iLen; i++) {

    if (arr[i].length != len) {
      return false;
    }
  }
  return true;
}

I'm not sure how you define a multi–dimensional "rectangular" array other than to say they must all have the same length. You can do that by having a function that loops over the members and if it's an array of arrays, recursively call itself until it gets an array of not arrays, then calls an isRectangularArray like function and passes the length to check against.

3 Comments

It appears that this would only apply to rectangular arrays (and not arrays of higher dimensions.)
He said rectangle, not square
This answer should (perhaps) be migrated to a more relevant question, discussing square arrays instead of rectangular arrays.
0

It is very simple and straightforward to use the recursive method to get the dimensional of an array without limited size:

const getArrayDimension = (array) => {
    if (!Array.isArray(array)) {
      return 0;
    }
    return 1 + getArrayDimension (array[0]);
};

Example:

console.log(getArrayDimension(123)); // 0 -> invalid
console.log(getArrayDimension([8])); // 1
console.log(getArrayDimension([[8, 11], [8, 9]])); // 2
console.log(getArrayDimension([[[8, 11], [5, 1]], [8, 9]])); // 3

1 Comment

The function's output isn't correct. The dimensions of the 2nd array should be [2,2] instead of 2.
-1

I did it this way, if you know the possible dimensions this is so much lighter :

//If i want to test if 2x2 or 3x3
if (typeof(array[0][0][0]) == "undefined")
{
  //stuff for array 3x3
}
else
{
  //stuff for array 2x2
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.