基于嵌套数组重新组合对象数组
Posted
技术标签:
【中文标题】基于嵌套数组重新组合对象数组【英文标题】:Regroup array of objects based on nested array 【发布时间】:2020-03-12 08:18:13 【问题描述】:我有一个对象数组。每个对象包含另一个内部数组。我想将每个内部数组作为外部对象,并将剩余的旧外部元素作为新创建的外部对象的子属性。
输入
data = [
name: "Sam",
ssn: 123,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "John",
ssn: 234,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "Mathew",
ssn: 345,
age: 25,
hobbies: [ name: "cricket" , name: "football" , name: "carroms"]
];
预期输出
[
name: "cricket",
person_details: [
name: "Sam", ssn: 123, age: 25 ,
name: "John", ssn: 234, age: 25 ,
name: "Mathew", ssn: 345, age: 25
]
,
name: "football",
person_details: [
name: "Sam", ssn: 123, age: 25 ,
name: "John", ssn: 234, age: 25 ,
name: "Mathew", ssn: 345, age: 25
]
,
name: "carroms",
person_details: [
name: "Mathew", ssn: 345, age: 25
]
]
我使用 Reduce 的尝试如下
this.data = this.data.reduce(
(a, x) => [...x.hobbies.map(h => ( ...x, hobbies: [h] ))],
[]
);
【问题讨论】:
为什么要在输出中输入hobbies:
?你为什么不在循环中访问h.name
?
当我看到这样的代码时,我想知道你是不是在尝试,或者你只是随机地将一些东西放在一起,所以我们不会因为没有显示尝试而关闭问题。
嘿伙计。我尝试了一些东西,但我不清楚如何通过添加扩展、箭头、es6 功能来简单地实现这一点。这可以很容易地使用多个 for 循环来完成,但我的目的是尽量减少复杂性和代码。
使用 spread 和 reduce 来缩短代码并不总能最小化复杂性。写清楚。
【参考方案1】:
您可以减少数组并为结果集寻找相同名称的项目。
var data = [ name: "Sam", ssn: 123, age: 25, hobbies: [ name: "cricket" , name: "football" ] , name: "John", ssn: 234, age: 25, hobbies: [ name: "cricket" , name: "football" ] , name: "Mathew", ssn: 345, age: 25, hobbies: [ name: "cricket" , name: "football" , name: "carroms" ] ],
result = data.reduce((r, hobbies, ...o ) =>
hobbies.forEach(( name ) =>
var group = r.find(q => q.name === name);
if (!group) r.push(group = name, person_details: [] );
group.person_details.push(o);
)
return r;
, []);
console.log(result);
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
你将如何学习这些东西? data.reduce((r, hobbies, ...o ) 这些类型的语法对我来说是新的。 你可以去destructuring和rest parameters...
/spread syntax ...
看看。【参考方案2】:
简单的Array.prototype.reduce()
与Array.prototype.forEach()
联手循环hobbies
的列表,再加上destructuring assignment 语法可以轻松解决问题:
const data = [name:"Sam",ssn:123,age:25,hobbies:[name:"cricket",name:"football"],name:"John",ssn:234,age:25,hobbies:[name:"cricket",name:"football"],name:"Mathew",ssn:345,age:25,hobbies:[name:"cricket",name:"football",name:"carroms"]],
result = data.reduce((r,hobbies, ...userData) => (
hobbies.forEach((name) => (
match = r.find((hobby) => hobby == name),
match ?
match['person_details'].push(...userData) :
r.push(hobby:name, person_details: [...userData])
))
, r), [])
console.log(result)
.as-console-wrappermin-height:100%;
【讨论】:
输出应该是一个数组,而不是一个对象【参考方案3】:改为创建一个索引该爱好的对象。迭代人员时,如果尚不存在,则使用 name
和 person_details
数组创建一个新对象,然后推送到 person_details
数组:
const data = [
name: "Sam",
ssn: 123,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "John",
ssn: 234,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "Mathew",
ssn: 345,
age: 25,
hobbies: [ name: "cricket" , name: "football" , name: "carroms"]
];
const peopleByHobbies = ;
for (const hobbies, ...personData of data)
for (const name of hobbies)
if (!peopleByHobbies[name]) peopleByHobbies[name] = name, person_details: [] ;
peopleByHobbies[name].person_details.push( ...personData );
const output = Object.values(peopleByHobbies);
console.log(output);
reduce
可以说是 not the right tool to use 用于这种事情,但如果你想使用它:
const data = [
name: "Sam",
ssn: 123,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "John",
ssn: 234,
age: 25,
hobbies: [ name: "cricket" , name: "football" ]
,
name: "Mathew",
ssn: 345,
age: 25,
hobbies: [ name: "cricket" , name: "football" , name: "carroms"]
];
const peopleByHobbies = data.reduce((peopleByHobbies, hobbies, ...personData ) =>
for (const name of hobbies)
if (!peopleByHobbies[name]) peopleByHobbies[name] = name, person_details: [] ;
peopleByHobbies[name].person_details.push( ...personData );
return peopleByHobbies;
, );
const output = Object.values(peopleByHobbies);
console.log(output);
【讨论】:
【参考方案4】:使用Array#reduce
。您可以使用Spread operator 像这样hobbies,...b
在每次迭代中传递对象
const arr = [ name: "Sam", ssn: 123, age: 25, hobbies: [ name: "cricket" , name: "football" ] , name: "John", ssn: 234, age: 25, hobbies: [ name: "cricket" , name: "football" ] , name: "Mathew", ssn: 345, age: 25, hobbies: [ name: "cricket" , name: "football" , name: "carroms" ] ];
const res = arr.reduce((acc, hobbies,...b) =>
hobbies.forEach(i =>
acc[i.name] = acc[i.name] ||
name: i.name,
persional_details: []
;
acc[i.name].persional_details.push(b)
)
return acc
, );
console.log(Object.values(res))
【讨论】:
以上是关于基于嵌套数组重新组合对象数组的主要内容,如果未能解决你的问题,请参考以下文章