如何基于Javascript中的多个数组属性对对象数组进行分组

时间:2019-12-18 07:36:48

标签: javascript arrays ecmascript-6

以一个对象数组为例,每个对象都具有某些数组属性,例如versionstargets。我想为每个versiontarget取消对象分组。

const myArray = [
  { 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
  { 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
  { 'name': 'c', versions: [1], targets: []}
]

上面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},
]

我考虑使用嵌套的for / forEach循环,但是几乎可以肯定的是,必须有一种更精确,更合理的方法来实现内置的es6函数。这就是我要的。

3 个答案:

答案 0 :(得分:6)

您可以使用fmap

.flatMap

或者具有更大的尺寸,生成器将变得非常有用:

  const notEmpty = arr => arr.length ? arr : [undefined];

  myArray.flatMap(({ name, versions, targets }) => notEmpty(versions).flatMap(version => notEmpty(targets).map(target => ({ name, version, target }))));

答案 1 :(得分:0)

您可以使用reduce方法:

const result = myArray.reduce((a, {name, versions, targets}) => {
  versions.forEach((el, ind) => {
      a.push({name, version: versions[ind], target: targets[ind]})
  });
  targets.forEach((el, ind) => {
      a.push({name, version: versions[ind], target: targets[ind]})
  });  
  return a;    
}, []);

一个例子:

const myArray = [
  { 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
  { 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
  { 'name': 'c', versions: [1], targets: []}
]


const result = myArray.reduce((a, {name, versions, targets}) => {
  versions.forEach((el, ind) => {
      a.push({name, version: versions[ind], target: targets[ind]})
  });
  targets.forEach((el, ind) => {
      a.push({name, version: versions[ind], target: targets[ind]})
 });  
  return a;
}, []);

console.log(result);

答案 2 :(得分:0)

const myArray = [
  { 'name': 'a', versions: [1, 2], targets: ['server1', 'server2'] },
  { 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3'] },
  { 'name': 'c', versions: [1], targets: [] }
]

const reducer = (acc, current) => {
  const { name, versions, targets } = current;
  for (let i = 0; i < versions.length; i++) {
    acc.push({ name, version: versions[i], target: targets[i] })
  }

  for (let i = 0; i < targets.length; i++) {
    acc.push({ name, version: versions[i], target: targets[i] })
  }

  return acc;
}

const ungroup = array => array.reduce(reducer, [])

console.log(ungroup(myArray))