如何在对象嵌套数组中按对象键分组?

时间:2019-05-17 15:55:53

标签: javascript arrays performance

我有一个嵌套的对象数组,我想对ID进行分组并形成一个新数组。这是我的数组:

mainArray = [
  { name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] },
  { name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] },
  { name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] }
]

我可以展平整个数组,但这似乎不是正确的方法。

我的新数组应如下所示:

result = [
  comapny_6: [
    {
      name: 'a',
      age: 10,
      desc: 'test1'
    },
  ],
  comapny_10: [
    {
      name: 'a',
      age: 10,
      desc: 'testa'
    },
    {
      name: 'c',
      age: 40,
      desc: 'test3'
    }
  ],

  company_30 :[
    {
      name: 'b',
      age: 20,
      desc: 'test2'
    },
    {
      name: 'c',
      age: 40,
      desc: 'testc'
    }
  ]
]

我愿意就最终数据结构的外观提出建议。最重要的是我想要groupBy id,以便我了解有关每个公司的信息。

3 个答案:

答案 0 :(得分:1)

您可以使用state.finalWord遍历数组并构造所需的对象输出。使用struct Iter { promise_handle handle = nullptr; HelloWorldState state; reference operator * () const { return state.currentWord; } pointer operator -> () const { return std::addressof(operator*()); } bool operator == (const Iter& other) { return !handle == !other.handle; } bool operator != (const Iter& other) { return !(*this == other); } Iter() = default; Iter(promise_handle handle) : handle(handle) { next(); } Iter& operator ++() { if (!handle) return *this; next(); return *this; } void next() { if (!handle) return; try { handle.resume(); if (!handle.done()) state = handle.promise().state; else { handle = nullptr; } } catch (...) { std::cerr << "@%$#@%#@$% \n"; } } }; 遍历reduce

forEach

答案 1 :(得分:1)

您可以先使用flatMap()创建一维数组,然后使用reduce()进行分组

const mainArray = [
  { name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] },
  { name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] },
  { name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] }
]

const flat = mainArray.flatMap(({company,...rest}) => company.map(a => ({...rest,...a})));

const res = flat.reduce((ac,{id,...rest}) => ((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac),{})
console.log(res)

说明

reduce()是在遍历所有数组后返回单个值的方法。累加器,即上述情况下的ac设置为空对象{}(这是传递给函数的第二个参数)

在每次迭代中,我们返回更新的累加器,该累加器变为ac,用于下一次迭代。所以我们从函数返回的就是表达式

((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac)

ac[ company _ $ {id} ]正在使用括号表示法,该表达式采用表达式company_${id}。与

相同
ac["company_" + id]

上面的行检查ac[company_${id}]中是否存在ac,然后是push() rest

如果尚未创建ac[company_${id}],他们将其设置为空数组[],则将push() rest设置为空数组。

最后一部分使用逗号运算符

((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac)

上面的整个表达式的计算结果为最后一个用逗号,分隔的值ac。因此,在每次迭代中,我们将rest推入各自的数组,并在末尾返回ac。该代码等效于

const res = flat.reduce((ac,{id,...rest}) => {
    //check if company id doesnot exist as key in ac then set it empty array
    if(!ac[`company_${id}`]) ac[`company_${id}`] = [];
    //push rest(which will be an object with all the keys expect id)
    ac[`company_${id}`].push(rest)
    //at last return ac
    return ac;
})

答案 2 :(得分:0)

您可以使用Array.reduce来实现这一目标,并可以通过Array.forEach来实现像这样的一系列公司内部的目标:

let data = [ { name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] }, { name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] }, { name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] } ] 

let result = data.reduce((r,{ name, age, company }) => {
  company.forEach(({ id, desc }) => 
   r[`company_${id}`] = (r[`company_${id}`] || []).concat({ name, age, desc }))
  return r
}, {})

console.log(result)

相关问题