如何根据键名合并 2 个数组并根据合并值排序?
How to merge 2 arrays based on a key name and sort based on the merged value?
假设我有两个列表
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
问题是如何将两个列表合并为一个堆栈,将相同的项目以数字递增并按数量排序?我的意思是最终结果应该是 ->
const listMerged = [{"apple":115}, {"banana": 50} , {"peach": 30}, {"kiwi": 13}, {"pearl": 10}, {"cherry": 5}, {"mango": 5}]
我知道它会是这样的:
sortListDesc(list) {
return obj.sort(function (l1,l2) {
return l2< l1 ? -1
: l2 >l1 ? 1
: 0
})
}
但不知道具体如何叠加数量,不如按数量排序。
您可以使用 forEach
迭代第二个列表,并使用 findIndex
检查第一个列表中是否存在相同的元素。如果元素不存在(-1),则将元素推入第一个列表。如果存在,则使用索引获取该对象,然后在 for..in
中更新其值
const listA = [{
"apple": 100
}, {
"banana": 50
}, {
"pearl": 10
}, {
"cherry": 5
}, {
"kiwi": 3
}]
const listB = [{
"peach": 30
}, {
"apple": 15
}, {
"kiwi": 10
}, {
"mango": 5
}]
let newArr = listB.forEach((item) => {
let ifElemPresentInListA = listA.findIndex((elem) => {
return Object.keys(elem)[0] === Object.keys(item)[0]
})
if (ifElemPresentInListA === -1) {
listA.push(item)
} else {
for (let keys in listA[ifElemPresentInListA]) {
listA[ifElemPresentInListA][keys] += Object.values(item)[0]
}
}
})
console.log(listA)
您可以这样使用 reduce
, and sort
and Object.values
:
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
, listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
let merged = Object.values(listA.concat(listB).reduce((acc, a) => {
const [k, v] = Object.entries(a)[0];
(acc[k] = acc[k] || {[k]: 0})[k] += v;
return acc;
}, {}));
merged.sort((a, b) => Object.values(b)[0] - Object.values(a)[0]);
console.log(merged);
或者,
使用reduce
,创建一个以所有水果为键,单个总和为值的对象。然后像这样使用 Object.entries
、sort
和 map
:
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
, listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
let merged2 = listA.concat(listB).reduce((acc, a) => {
const [k, v] = Object.entries(a)[0];
acc[k] = (acc[k] || 0) + v;
return acc;
}, {});
const final = Object.entries(merged2)
.sort(([, v1], [, v2]) => v2 - v1)
.map(([k, v]) => ({[k]: v}))
console.log(final);
我想我的代码比 brk
的代码稍微干净一些
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
const both = Object.assign({}, ... listA, ... listB); // concatenate both lists and convert them to an object
const lA = Object.assign({}, ...listA); // convert listA to an object
const lB = Object.assign({}, ...listB);
var result = Object.keys(both).map( (a) => { // mapping sums the values and yields an array
var sum = {};
sum [a] =(lA[a] ? lA[a] : 0) + (lB[a] ? lB[a] : 0);
return sum;
});
// sorting in desc order (hence b - a ) based on values (hence b[Object.keys(b)]) rather than keys
result.sort((a,b) => b[Object.keys(b)] - a[Object.keys(a)] );
之所以复杂,是因为您将值存储为数组。
我相信这不是最好的方式,因为数组可以有多个具有相同键的元素。例如。你可以得到这样的结果:
const listA = [{"apple":100},...,{"apple":10}]
这是有效的,但可能会产生问题。
我建议您考虑将其用作对象,例如:
const listA = {{'apple': 100}, {'banana':50}}
这将大大简化代码并确保您没有重复项
希望对您有所帮助!
假设我有两个列表
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
问题是如何将两个列表合并为一个堆栈,将相同的项目以数字递增并按数量排序?我的意思是最终结果应该是 ->
const listMerged = [{"apple":115}, {"banana": 50} , {"peach": 30}, {"kiwi": 13}, {"pearl": 10}, {"cherry": 5}, {"mango": 5}]
我知道它会是这样的:
sortListDesc(list) {
return obj.sort(function (l1,l2) {
return l2< l1 ? -1
: l2 >l1 ? 1
: 0
})
}
但不知道具体如何叠加数量,不如按数量排序。
您可以使用 forEach
迭代第二个列表,并使用 findIndex
检查第一个列表中是否存在相同的元素。如果元素不存在(-1),则将元素推入第一个列表。如果存在,则使用索引获取该对象,然后在 for..in
const listA = [{
"apple": 100
}, {
"banana": 50
}, {
"pearl": 10
}, {
"cherry": 5
}, {
"kiwi": 3
}]
const listB = [{
"peach": 30
}, {
"apple": 15
}, {
"kiwi": 10
}, {
"mango": 5
}]
let newArr = listB.forEach((item) => {
let ifElemPresentInListA = listA.findIndex((elem) => {
return Object.keys(elem)[0] === Object.keys(item)[0]
})
if (ifElemPresentInListA === -1) {
listA.push(item)
} else {
for (let keys in listA[ifElemPresentInListA]) {
listA[ifElemPresentInListA][keys] += Object.values(item)[0]
}
}
})
console.log(listA)
您可以这样使用 reduce
, and sort
and Object.values
:
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
, listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
let merged = Object.values(listA.concat(listB).reduce((acc, a) => {
const [k, v] = Object.entries(a)[0];
(acc[k] = acc[k] || {[k]: 0})[k] += v;
return acc;
}, {}));
merged.sort((a, b) => Object.values(b)[0] - Object.values(a)[0]);
console.log(merged);
或者,
使用reduce
,创建一个以所有水果为键,单个总和为值的对象。然后像这样使用 Object.entries
、sort
和 map
:
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
, listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
let merged2 = listA.concat(listB).reduce((acc, a) => {
const [k, v] = Object.entries(a)[0];
acc[k] = (acc[k] || 0) + v;
return acc;
}, {});
const final = Object.entries(merged2)
.sort(([, v1], [, v2]) => v2 - v1)
.map(([k, v]) => ({[k]: v}))
console.log(final);
我想我的代码比 brk
的代码稍微干净一些const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
const both = Object.assign({}, ... listA, ... listB); // concatenate both lists and convert them to an object
const lA = Object.assign({}, ...listA); // convert listA to an object
const lB = Object.assign({}, ...listB);
var result = Object.keys(both).map( (a) => { // mapping sums the values and yields an array
var sum = {};
sum [a] =(lA[a] ? lA[a] : 0) + (lB[a] ? lB[a] : 0);
return sum;
});
// sorting in desc order (hence b - a ) based on values (hence b[Object.keys(b)]) rather than keys
result.sort((a,b) => b[Object.keys(b)] - a[Object.keys(a)] );
之所以复杂,是因为您将值存储为数组。
我相信这不是最好的方式,因为数组可以有多个具有相同键的元素。例如。你可以得到这样的结果:
const listA = [{"apple":100},...,{"apple":10}]
这是有效的,但可能会产生问题。
我建议您考虑将其用作对象,例如:
const listA = {{'apple': 100}, {'banana':50}}
这将大大简化代码并确保您没有重复项
希望对您有所帮助!