用Javascript中的键值对展平嵌套数组

时间:2019-08-08 15:49:15

标签: javascript arrays

给出这样的数组:

[
    { id: 1, emailAddresses: ["bill@test.com", "bob@test.com"] },
    { id: 2, emailAddresses: ["sarah@test.com" },
    { id: 3, emailAddresses: ["jane@test.com", "laura@test.com", "paul@test.com"]
]

如何使用Javascript将其简化为这样的数组:

[
    { id: 1, emailAddress: "bill@test.com" },
    { id: 1, emailAddress: "bob@test.com" },
    { id: 2, emailAddress: "sarah@test.com" },
    { id: 3, emailAddress: "jane@test.com" },
    { id: 3, emailAddress: "laura@test.com" },
    { id: 3, emailAddress: "paul@test.com" }
 ]

我已经了解了函数reduceflatmap等,并在SO中阅读了很多有关使用它们的问题,但我找不到任何要问的问题与此完全相同,我无法使用这些功能来做到这一点。

5 个答案:

答案 0 :(得分:2)

您可以使用flatMap

const input = [
    { id: 1, emailAddresses: ["bill@test.com", "bob@test.com"] },
    { id: 2, emailAddresses: ["sarah@test.com"] },
    { id: 3, emailAddresses: ["jane@test.com", "laura@test.com", "paul@test.com"] }
]

const output = input.flatMap(o => 
    o.emailAddresses.map(e => ({ id: o.id, emailAddress: e }) )
)

console.log(output)

如果不支持flatMap,则可以使用嵌套的for...of循环:

const input = [{id:1,emailAddresses:["bill@test.com","bob@test.com"]},{id:2,emailAddresses:["sarah@test.com"]},{id:3,emailAddresses:["jane@test.com","laura@test.com","paul@test.com"]}];
const output = []

for (const { id, emailAddresses } of input)
  for (const emailAddress of emailAddresses)
    output.push({ id, emailAddress })

console.log(output)

答案 1 :(得分:2)

我们可以使用Array.prototype.reduce遍历数组中的每个对象,并考虑emailAddress属性数组中的多个值,并为每个对象创建 separate 对象,最后累积新数组(r)中的新对象:

const data = [
    { id: 1, emailAddresses: ["bill@test.com", "bob@test.com"] },
    { id: 2, emailAddresses: ["sarah@test.com"] },
    { id: 3, emailAddresses: ["jane@test.com", "laura@test.com", "paul@test.com"]}
]
const flat = data.reduce((r, e) => {
  e.emailAddresses.forEach((obj) => r.push({id: e.id, emailAddresses : obj }));
  return r;
}, []);
console.log(flat);   

答案 2 :(得分:2)

您可以映射数据,然后使用reduce来平整结果数组:

const result = data
  .map(datum => {
    return datum.emailAddresses.map(emailAddress => {
      return { id: datum.id, emailAddress };
    });
  })
  .reduce((result, current) => {
    return [...result, ...current];
  }, []);

答案 3 :(得分:2)

您可以使用reduce和map

const data = [
    { id: 1, emailAddresses: ["bill@test.com", "bob@test.com"] },
    { id: 2, emailAddresses: ["sarah@test.com"] },
    { id: 3, emailAddresses: ["jane@test.com", "laura@test.com", "paul@test.com"]}
]

const flat = (toFlatten) => 
  toFlatten.reduce((r,c)=> {
    r.push(...c.emailAddresses.map(email=>({id: c.id, emailAddress: email})))
    return r
  }, [])

console.log(flat(data))

答案 4 :(得分:2)

这是一种不使用任何数组原型的解决方案,而是使用了函数生成器。

下面的脚本迭代数组,获取元素{emailAddresses除外)的所有键(分别处理),并为每个电子邮件地址生成一个由单个电子邮件地址和其余数据填充的对象。

此解决方案仅迭代原始数组一次。

由于它使用函数生成器,因此该解决方案得到了广泛的支持,尽管babel或TSC可以轻松为其添加兼容性,但由于它不支持函数生成器,因此只能在IE上使用。

const input = [
    { id: 1, emailAddresses: ["bill@test.com", "bob@test.com"] },
    { id: 2, emailAddresses: ["sarah@test.com"] },
    { id: 3, emailAddresses: ["jane@test.com", "laura@test.com", "paul@test.com"] }
];

function* flattenEmailAddresses(arr) {
  for (var {emailAddresses, ...keys} of arr) {
    for (var emailAddress of emailAddresses) yield {...keys, emailAddress};
  }
}

console.log([...flattenEmailAddresses(input)]);