问题
assume I have two list
const listA = [{"apple":100}, {"banana": 50}, {"pearl": 10}, {"cherry": 5}, {"kiwi": 3}]
const listB = [{"peach": 30}, {"apple": 15}, {"kiwi": 10}, {"mango": 5}]
The question is how do I merge two list into one stack up the same item with number increment and sort by the qty? I mean the final result should be ->
const listMerged = [{"apple":115}, {"banana": 50} , {"peach": 30}, {"kiwi": 13}, {"pearl": 10}, {"cherry": 5}, {"mango": 5}]
I know it is gonna be something like :
sortListDesc(list) {
return obj.sort(function (l1,l2) {
return l2< l1 ? -1
: l2 >l1 ? 1
: 0
})
}
but do not know exactly how to stack up the number, than sort by qty number.
回答1:
You can use reduce, and sort and Object.values like this:
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);
Or,
Using reduce
, create an object with all the fruits as keys and individual sum as values. Then use Object.entries, sort
and map
like this:
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);
回答2:
You can iterate the second list using forEach
and check if the same element is present in the first list using findIndex
. If the element is not present(-1) then push the element in first list. If it is present then using the index get that object and then update its value inside a 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)
回答3:
I think I have a slightly cleaner code than the one from 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)] );
The complexity is due to the fact that you store the values as an array.
I believe this is not the best way to have it for the reason that array can have multiple elements with the same keys. E.g. you can end up with something like this:
const listA = [{"apple":100},...,{"apple":10}]
which is valid but can make a problem.
I suggest you to consider using it just as an Object e.g.:
const listA = {{'apple': 100}, {'banana':50}}
this will simplify the code significantly and make sure you don't have duplicates
Hope that helps!
来源:https://stackoverflow.com/questions/54194211/how-to-merge-2-arrays-based-on-a-key-name-and-sort-based-on-the-merged-value