JS(ES6):根据id合并数组并拼接子数组
JS (ES6): Merge arrays based on id and concatenating sub arrays
我有两个数组,如下所示:
const persons = [
{
id: 1,
name: 'Peter',
job: 'Programmer'
},
{
id: 2,
name: 'Jeff',
job: 'Architect'
},
];
const salaries = [
{
id: 1,
salary: 3000,
departments: ['A', 'B']
},
{
id: 1,
salary: 4000,
departments: ['A', 'C']
},
{
id: 2,
salary: 4000,
departments: ['C', 'D']
}
];
现在我需要以某种方式将这些数组合并为一个,以便每个 id 只存在一次。应该替换相同的键,除了它是一个数组,然后我希望它们 add/concat。所以期望的结果应该是这样的:
const result = [
{
id: 1,
name: 'Peter',
job: 'Programmer',
salary: 4000,
departments: ['A', 'B', 'C']
},
{
id: 2,
name: 'Jeff',
job: 'Architect',
salary: 4000,
departments: ['C', 'D']
}
];
我已经试过了:
// double id's, arrays get replaced
Object.assign({}, persons, salaries)
// loadsh: double id's, arrays get concatenated
_.mergeWith(persons, salaries, (objValue, srcValue) => {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
});
// gives me a map but replaces arrays
new Map(salaries.map(x => [x.id, x])
有人知道如何实现吗?
您可以使用 Map
并迭代所有属性并检查类型以将唯一值添加到数组。
var persons = [{ id: 1, name: 'Peter', job: 'Programmer' }, { id: 2, name: 'Jeff', job: 'Architect' }],
salaries = [{ id: 1, salary: 3000, departments: ['A', 'B'] }, { id: 1, salary: 4000, departments: ['A', 'C'] }, { id: 2, salary: 4000, departments: ['C', 'D'] }],
result = Array.from(
salaries
.reduce(
(m, o) => {
var t = m.get(o.id) || {};
Object.keys(o).forEach(k => {
if (Array.isArray(o[k])) {
t[k] = t[k] || [];
o[k].forEach(v => t[k].includes(v) || t[k].push(v));
} else if (t[k] !== o[k]) {
t[k] = o[k];
}
});
return m;
},
persons.reduce((m, o) => m.set(o.id, Object.assign({}, o)), new Map)
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
你可以concat the arrays, than combine all items with the same id
using Array.reduce()
, and a Map。
将具有相同id
的对象组合起来,从Map中获取对象。迭代新的Object.entries()
with Array.forEach()
. Check if existing value is an array, if not assign the value. If it is an array, combine the arrays, and make the items unique using a Set with array spread.
要将 Map 转换回数组,可以展开 Map.values()
迭代器。
const persons = [{"id":1,"name":"Peter","job":"Programmer"},{"id":2,"name":"Jeff","job":"Architect"}];
const salaries = [{"id":1,"salary":3000,"departments":["A","B"]},{"id":1,"salary":4000,"departments":["A","C"]},{"id":2,"salary":4000,"departments":["C","D"]}];
const result = [...persons.concat(salaries)
.reduce((r, o) => {
r.has(o.id) || r.set(o.id, {});
const item = r.get(o.id);
Object.entries(o).forEach(([k, v]) =>
item[k] = Array.isArray(item[k]) ?
[...new Set([...item[k], ...v])] : v
);
return r;
}, new Map()).values()];
console.log(result);
您可以使用 map()
, filter()
, reduce()
, Object.assign()
and Spread syntax
来获得所需的结果。
演示
const persons = [{
id: 1,
name: 'Peter',
job: 'Programmer'
}, {
id: 2,
name: 'Jeff',
job: 'Architect'
}],
salaries = [{
id: 1,
salary: 3000,
departments: ['A', 'B']
}, {
id: 1,
salary: 4000,
departments: ['A', 'C']
}, {
id: 2,
salary: 4000,
departments: ['C', 'D']
}];
let output = persons.map(obj => {
let filter = salaries.filter(v => v.id == obj.id);
if (filter) {
let departments = filter.reduce((r, v) => [...v.departments, ...r], []);
Object.assign(obj, {
salary: filter[filter.length - 1].salary,
departments: departments.filter((item, pos) => departments.indexOf(item) == pos).sort()
});
}
return obj;
});
console.log(output)
我有两个数组,如下所示:
const persons = [
{
id: 1,
name: 'Peter',
job: 'Programmer'
},
{
id: 2,
name: 'Jeff',
job: 'Architect'
},
];
const salaries = [
{
id: 1,
salary: 3000,
departments: ['A', 'B']
},
{
id: 1,
salary: 4000,
departments: ['A', 'C']
},
{
id: 2,
salary: 4000,
departments: ['C', 'D']
}
];
现在我需要以某种方式将这些数组合并为一个,以便每个 id 只存在一次。应该替换相同的键,除了它是一个数组,然后我希望它们 add/concat。所以期望的结果应该是这样的:
const result = [
{
id: 1,
name: 'Peter',
job: 'Programmer',
salary: 4000,
departments: ['A', 'B', 'C']
},
{
id: 2,
name: 'Jeff',
job: 'Architect',
salary: 4000,
departments: ['C', 'D']
}
];
我已经试过了:
// double id's, arrays get replaced
Object.assign({}, persons, salaries)
// loadsh: double id's, arrays get concatenated
_.mergeWith(persons, salaries, (objValue, srcValue) => {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
});
// gives me a map but replaces arrays
new Map(salaries.map(x => [x.id, x])
有人知道如何实现吗?
您可以使用 Map
并迭代所有属性并检查类型以将唯一值添加到数组。
var persons = [{ id: 1, name: 'Peter', job: 'Programmer' }, { id: 2, name: 'Jeff', job: 'Architect' }],
salaries = [{ id: 1, salary: 3000, departments: ['A', 'B'] }, { id: 1, salary: 4000, departments: ['A', 'C'] }, { id: 2, salary: 4000, departments: ['C', 'D'] }],
result = Array.from(
salaries
.reduce(
(m, o) => {
var t = m.get(o.id) || {};
Object.keys(o).forEach(k => {
if (Array.isArray(o[k])) {
t[k] = t[k] || [];
o[k].forEach(v => t[k].includes(v) || t[k].push(v));
} else if (t[k] !== o[k]) {
t[k] = o[k];
}
});
return m;
},
persons.reduce((m, o) => m.set(o.id, Object.assign({}, o)), new Map)
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
你可以concat the arrays, than combine all items with the same id
using Array.reduce()
, and a Map。
将具有相同id
的对象组合起来,从Map中获取对象。迭代新的Object.entries()
with Array.forEach()
. Check if existing value is an array, if not assign the value. If it is an array, combine the arrays, and make the items unique using a Set with array spread.
要将 Map 转换回数组,可以展开 Map.values()
迭代器。
const persons = [{"id":1,"name":"Peter","job":"Programmer"},{"id":2,"name":"Jeff","job":"Architect"}];
const salaries = [{"id":1,"salary":3000,"departments":["A","B"]},{"id":1,"salary":4000,"departments":["A","C"]},{"id":2,"salary":4000,"departments":["C","D"]}];
const result = [...persons.concat(salaries)
.reduce((r, o) => {
r.has(o.id) || r.set(o.id, {});
const item = r.get(o.id);
Object.entries(o).forEach(([k, v]) =>
item[k] = Array.isArray(item[k]) ?
[...new Set([...item[k], ...v])] : v
);
return r;
}, new Map()).values()];
console.log(result);
您可以使用 map()
, filter()
, reduce()
, Object.assign()
and Spread syntax
来获得所需的结果。
演示
const persons = [{
id: 1,
name: 'Peter',
job: 'Programmer'
}, {
id: 2,
name: 'Jeff',
job: 'Architect'
}],
salaries = [{
id: 1,
salary: 3000,
departments: ['A', 'B']
}, {
id: 1,
salary: 4000,
departments: ['A', 'C']
}, {
id: 2,
salary: 4000,
departments: ['C', 'D']
}];
let output = persons.map(obj => {
let filter = salaries.filter(v => v.id == obj.id);
if (filter) {
let departments = filter.reduce((r, v) => [...v.departments, ...r], []);
Object.assign(obj, {
salary: filter[filter.length - 1].salary,
departments: departments.filter((item, pos) => departments.indexOf(item) == pos).sort()
});
}
return obj;
});
console.log(output)