6

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.)?

4

6 回答 6

10

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

于 2012-12-12T02:50:23.463 回答
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 :) )

于 2012-12-11T06:39:27.867 回答
1

How about using Array.every.

Example:

var firstLen = ar[0].length;

var isRectangular = ar.every(function(item) {
return item.length == firstLen;
}
于 2012-12-11T06:14:31.000 回答
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;
}
于 2012-12-11T06:17:28.533 回答
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.

于 2012-12-11T06:36:25.327 回答
-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
}
于 2016-09-07T13:33:07.343 回答