EN VI

Arrays - Checking if an n-dimensional array input is valid?

2024-03-12 04:30:05
Arrays - Checking if an n-dimensional array input is valid

I'm experimenting with make my own Tensor class (n-dimensional arrays) in typescript. The class stores its data in a 1D array property, and also stores the shape of the data in a separate array for use when indexing into the data.

I want to create a function similar to that of numpy.array, a function that takes in the data as a multi-dimensional array, stores its elements as a flat array and then extracts the shape.

but it also has to validate if the input array is valid (I believe the correct phrase is "has a homogeneous shape")

example 1

when the function is given the following input:

data = [
  [[1, 2], [3, 4]],
  [[5, 6], [7, 8]],
]

it should return a tensor with the shape (2, 2, 2) and the [1, 2, 3, ..., 8] elements as a flat array for the data inside the tensor.

example 2

however, when given the following input:

data = [
  [[1], [3, 4]],
  [[5, 6], [7, 8]],
]

it should fail because there is a sub-array in there that only contains a 1 which is inconsistent with the rest of the array.

example 3

if given this input:

data = [
  [[1], 2],
  [3, 4],
]

this should also fail not because the 1 is inside a sub-array which is also inconsistent with the rest of the array.

numpy.array function seems to be able to detect these cases and raise errors accordingly, I couldn't find information about an algorithm that can check for this, perhaps I don't know what to look for, any help is appreciated.

note: I realize it's probably better to use an existing library that can do this and move on, but this is only an experimental project that I'm doing only for the sake of learning, I don't have much knowledge about tensors, so if you believe there are other things I need to learn first before going to implement this, then a pointer on what I should learn would be appreciated.

Solution:

This is probably highly inefficient, but it works for an experimental project. The output contains an extra '0' for the dimensions, as this is the inner dimension. Either drop the first element of this array, or handle the case, but it looks reasonable for me to say, that a number can be seen as an array with dimension zero.

/// arraysEqual taken from https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
function arraysEqual(a: any[], b: any[]) {
  if (a === b) return true;
  if (a == null || b == null) return false;
  if (a.length !== b.length) return false;

  // If you don't care about the order of the elements inside
  // the array, you should sort both arrays here.
  // Please note that calling sort on an array will modify that array.
  // you might want to clone your array first.

  for (var i = 0; i < a.length; ++i) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}

function testArray(x: any): [number[], number[]] {
  if (Array.isArray(x)) {
    let lastDim: number[] | undefined = undefined;
    let numbers: number[] = [];
    if (x.length === 0) {
      throw "Empty array";
    }
    for (const el of x) {
      const [d, n] = testArray(el);
      if (lastDim === undefined) {
        lastDim = d;
      }

      if (!arraysEqual(lastDim, d)) {
        throw "Dimensions not equal";
      }
      numbers.push(...n);
    }
    if (lastDim === undefined) {
      throw "Should never happen, but this line makes typescript happy :)";
    }
    lastDim.push(x.length);
    return [lastDim, numbers];
  } else if (typeof x === "number") {
    return [[0], [x]];
  } else {
    throw "Not an array or a number";
  }
}

const data1 = [
  [
    [1, 2],
    [3, 4],
  ],
  [
    [5, 6],
    [7, 8],
  ],
];

console.log(testArray(data1));

const data2 = [
  [[1], [3, 4]],
  [
    [5, 6],
    [7, 8],
  ],
];

try {
  console.log(testArray(data2));
} catch (e) {
  console.error(e);
}

const data3 = [
  [[1], 2],
  [3, 4],
];

try {
  console.log(testArray(data3));
} catch (e) {
  console.error(e);
}

[LOG]: [[0, 2, 2, 2], [1, 2, 3, 4, 5, 6, 7, 8]] 
[ERR]: "Dimensions not equal" 
[ERR]: "Dimensions not equal" 
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login