我正在尝试在打字稿中制作我自己的张量类(n 维数组)。 该类将其数据存储在一维数组属性中,并将数据的形状存储在单独的数组中,以便在索引数据时使用。
我想创建一个类似于
numpy.array
的函数,该函数将数据作为多维数组接收,将其元素存储为平面数组,然后提取形状。
但它还必须验证输入数组是否有效(我相信正确的短语是“具有均匀的形状”)
当函数给出以下输入时:
data = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
]
它应该返回一个形状为 (2, 2, 2) 和 [1, 2, 3, ..., 8] 元素的张量作为张量内数据的平面数组。
但是,当给出以下输入时:
data = [
[[1], [3, 4]],
[[5, 6], [7, 8]],
]
它应该失败,因为其中有一个子数组只包含一个 1 ,它与数组的其余部分不一致。
如果给出此输入:
data = [
[[1], 2],
[3, 4],
]
这也应该失败,不是因为 1 位于子数组内,该子数组也与数组的其余部分不一致。
numpy.array
函数似乎能够检测这些情况并相应地引发错误,我找不到有关可以检查此情况的算法的信息,也许我不知道要寻找什么,不胜感激。
注意:我意识到使用现有的库可能更好,可以做到这一点并继续,但这只是一个实验项目,我只是为了学习而做,我对此没有太多了解张量,所以如果您认为在实现这个之前我需要先学习其他东西,那么我将不胜感激。
这可能效率非常低,但它适用于实验项目。输出包含一个额外的维度“0”,因为这是内部维度。要么删除该数组的第一个元素,要么处理这种情况,但对我来说,数字可以被视为维度为零的数组似乎是合理的。
/// 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"