关于对象数组句柄-javascript:
我有一个项目数组,如:
// all projects
var projects = [{
name: '',
company: 'c1',
skills: ['s1', 's4']
}, {
name: 'p2',
company: 'c2',
skills: ['s2']
}, {
name: 'p3',
company: 'c3',
skills: ['s3']
}, {
name: 'p4',
company: 'c1',
skills: ['s1', 's5']
}, {
name: 'p5',
company: 'c2',
skills: ['s3']
}]
如果项目在公司中使用过,我想收集每个公司的技能(如果p1项目使用s1技能,则收集它。)
// results
var companySkills = [{
company: 'c1',
skills: ['s1', 's4', 's5']
}, {
company: 'c2',
skills: ['s2', 's3']
}, {
company: 'c3',
skills: ['s3']
}]
我现在写的是什么
// what I writing now, I want to improve the code.
var companySkills = []
projects.forEach(project => {
let each = {}
const alreadyCompany = companySkills.find(companySkill => companySkill.company === project.company)
if (!alreadyCompany) {
each.company = project.company
each.skills = []
}
project.skills.forEach(skill => {
if (alreadyCompany) {
alreadyCompany.skills = [skill, ...alreadyCompany.skills]
} else {
each.skills = [skill, ...each.skills]
}
})
if (!alreadyCompany) {
companySkills = [each, ...companySkills]
}
})
// final results
companySkills = companySkills.map(companySkill => ({
company: companySkill.company,
skills: [...new Set(companySkill.skills)]
}))
有没有更好的方法编写更简洁的代码?
答案 0 :(得分:1)
我建议reduce
放入由company
索引的对象中,然后可以将其推入累加器中相应对象中的skills
数组中(必要时首先创建它) ):
const projects=[{name:'',company:'c1',skills:['s1','s4']},{name:'p2',company:'c2',skills:['s2']},{name:'p3',company:'c3',skills:['s3']},{name:'p4',company:'c1',skills:['s5']},{name:'p5',company:'c2',skills:['s3']}]
const companySkillsObj = projects.reduce((a, { company, skills }) => {
if (!a[company]) a[company] = { company, skills: [] };
a[company].skills.push(...skills);
return a;
}, {});
const companySkills = Object.values(companySkillsObj);
console.log(companySkills);
如果您想避免技能重复,请改用Set
:
var projects=[{name:'',company:'c1',skills:['s1','s4']},{name:'p2',company:'c2',skills:['s2']},{name:'p3',company:'c3',skills:['s3']},{name:'p4',company:'c1',skills:['s1','s5']},{name:'p5',company:'c2',skills:['s3']}];
const companySkillsObj = projects.reduce((a, { company, skills }) => {
if (!a[company]) a[company] = new Set();
skills.forEach(a[company].add, a[company]);
return a;
}, {});
const companySkills = Object.entries(companySkillsObj)
.map(([company, set]) => ({ company, skills: [...set] }));
console.log(companySkills);
答案 1 :(得分:0)
您可以在ES6 reduce
中使用Map
方法,然后获取值。
var projects = [{"name":"","company":"c1","skills":["s1","s4"]},{"name":"p2","company":"c2","skills":["s2"]},{"name":"p3","company":"c3","skills":["s3"]},{"name":"p4","company":"c1","skills":["s5"]},{"name":"p5","company":"c2","skills":["s3"]}]
var result = projects.reduce((r, {company, skills}) => {
if(!r.get(company)) r.set(company, {company, skills});
else r.get(company).skills.push(...skills);
return r;
}, new Map()).values()
console.log(Array.from(result))
要使技能独特而不重复元素,可以先将其设置为Set
,然后在最后一次迭代时将其转换为数组。
var projects = [{"name":"","company":"c1","skills":["s1","s4"]},{"name":"p2","company":"c2","skills":["s2"]},{"name":"p3","company":"c3","skills":["s3"]},{"name":"p4","company":"c1","skills":["s1", "s1", "s5", "s5", "s1"]},{"name":"p5","company":"c2","skills":["s3"]}]
var result = projects.reduce((r, {company, skills}, i, arr) => {
if(!r.get(company)) r.set(company, {company, skills: new Set(skills)});
else skills.forEach(skill => r.get(company).skills.add(skill))
if(!arr[i + 1]) r.forEach(p => p.skills = [...p.skills])
return r;
}, new Map()).values()
console.log(Array.from(result))
答案 2 :(得分:0)
除了其他答案外,还有一种没有Map和Set的方法。
const projects = [{
name: '',
company: 'c1',
skills: ['s1', 's4']
}, {
name: 'p2',
company: 'c2',
skills: ['s2']
}, {
name: 'p3',
company: 'c3',
skills: ['s3']
}, {
name: 'p4',
company: 'c1',
skills: ['s1', 's5']
}, {
name: 'p5',
company: 'c2',
skills: ['s3']
}];
const groupProjects = (array) =>
// Deconstruct and keep the properties we want
array.reduce((acc, { company, skills }) => {
// find if we already have added this company
const index = acc.findIndex((a) => a.company === company);
if (index === -1) return acc.concat(({ company, skills }));
skills.forEach((skill) => {
// add unique skills
if (!acc[index].skills.includes(skill)) acc[index].skills.push(skill);
});
return acc;
}, []);
console.log(groupProjects(projects));