如何根据Javascript中的多个数组属性取消对象数组的分组

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 函数左右。这就是我的要求。

Jon*_*lms 6

你可以使用.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)