vah*_*det 3 javascript arrays ecmascript-6
想想一个对象数组,它们中的每一个都具有某些数组属性,例如versions, targets。我想为每个version和取消组合对象target。
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
Run Code Online (Sandbox Code Playgroud)
myArray以上所需的输出是:
[
{ 'name': 'a', version: 1, target: 'server1'},
{ 'name': 'a', version: 1, target: 'server2'},
{ 'name': 'a', version: 2, target: 'server1'},
{ 'name': 'a', version: 2, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server1'},
{ 'name': 'b', version: undefined, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server3'},
{ 'name': 'c', version: 1, target: undefined},
]
Run Code Online (Sandbox Code Playgroud)
我考虑过使用嵌套for/forEach循环,但几乎可以肯定,必须有一种更精确、更合理的方法来实现它内置的 es6 函数左右。这就是我的要求。
你可以使用.flatMap:
const notEmpty = arr => arr.length ? arr : [undefined];
myArray.flatMap(({ name, versions, targets }) => notEmpty(versions).flatMap(version => notEmpty(targets).map(target => ({ name, version, target }))));
Run Code Online (Sandbox Code Playgroud)
或者有更多维度,生成器变得非常有用:
function* cartesian(obj, key, ...keys) {
if(!key) {
yield obj;
return;
}
const { [key + "s"]: entries, ...rest } = obj;
for(const entry of (entries.length ? entries : [undefined])) {
yield* cartesian({ [key]: entry, ...rest }, ...keys);
}
}
myArray.flatMap(it => cartesian(it, "version", "target"))
Run Code Online (Sandbox Code Playgroud)