我正在构建一个组合函数,该函数产生输入列表的carried乘积.作为一个怪癖,我想支持枚举作为潜在列表.我可能会在稍后扩展它以支持实际的集合.
我有一个非常有效的代码:
type EnumOrArray = { [key: string]: any; } | any[];
export function cartesian(...inputs: EnumOrArray[]): any[][] {
const itemGroups: any[][] = inputs.map(input => {
if (Array.isArray(input)) {
return input; // Directly return if input is an array
} else {
// Only work with the enum's keys (names), then convert them to their numeric values
const originalKeys = Object.keys(input).filter(key => isNaN(Number(key)));
return originalKeys.map(key => input[key]);
}
});
// Recursive function to generate combinations (remains unchanged)
function generateCartesianProduct(groups: any[][], prefix: any[] = []): any[][] {
if (!groups.length) return [prefix];
const firstGroup = groups[0];
const restGroups = groups.slice(1);
let result: any[][] = [];
firstGroup.forEach(item => {
result = result.concat(generateCartesianProduct(restGroups, [...prefix, item]));
});
return result;
}
return generateCartesianProduct(itemGroups);
}
...但这是一个类型的防火墙,只生成any [][]类型的输出,这并不令人满意.
例如,如果我使用这个:
enum Color {
Red = 'red',
Green = 'green',
Blue = 'blue'
}
enum Size {
Small = 1,
Medium = 10,
Large = 100
}
const numbers = [1, 2];
const combos = cartesian(Color, numbers, Size);
它产生了正确的价值:
[
[ 'red', 1, 1 ], [ 'red', 1, 10 ],
[ 'red', 1, 100 ], [ 'red', 2, 1 ],
[ 'red', 2, 10 ], [ 'red', 2, 100 ],
[ 'green', 1, 1 ], [ 'green', 1, 10 ],
[ 'green', 1, 100 ], [ 'green', 2, 1 ],
[ 'green', 2, 10 ], [ 'green', 2, 100 ],
[ 'blue', 1, 1 ], [ 'blue', 1, 10 ],
[ 'blue', 1, 100 ], [ 'blue', 2, 1 ],
[ 'blue', 2, 10 ], [ 'blue', 2, 100 ]
]
但我希望它是[Color, number, Size][]
型的,而不是any[][]
型的.
我认为答案是用可变泛型类型做一些聪明的事情,但我想不出来.