'I want to combine the objects in the array, how should I change them?
const data = [
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "13inch",
optionPrice: 0,
qty: 2,
},
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "15inch",
optionPrice: 1000,
qty: 1,
},
]
const results = data.reduce((prev, curr) => {
if (prev.productId === curr.productId) {
???
}
}, []);
output
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
option: [
{ optionName: "13inch", optionPrice: 0, qty: 2 },
{ optionName: "15inch", optionPrice: 1000, qty: 1 },
],
},
If the productId is the same as the code above,
I want to remove the overlapping part of key:value, create an option object for the non-overlapping part, and create an array object for value.
I tried to solve it by using reduce, but it didn't go well, so I'm asking you a question.
Solution 1:[1]
One method is to convert array into object, and use productId as key:
const data = [
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "13inch",
optionPrice: 0,
qty: 2,
},
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "15inch",
optionPrice: 1000,
qty: 1,
},
{
productId: 4,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "15inch",
optionPrice: 1000,
qty: 1,
},
]
const results = Object.values(data.reduce((prev, curr) => {
if (prev[curr.productId])
{
const obj = prev[curr.productId];
if (!obj.option)
{
obj.option = [];
obj.option.push({optionName: obj.optionName, optionPrice: obj.optionPrice, qty: obj.qty});
delete obj.optionName;
delete obj.optionPrice;
delete obj.qty;
}
prev[curr.productId].option.push({optionName: curr.optionName, optionPrice: curr.optionPrice, qty: curr.qty});
}
else
prev[curr.productId] = Object.assign({}, curr);
return prev;
}, {}));
console.log(results);
Solution 2:[2]
Here's a pure, functional approach which won't mutate any part of your existing array data:
function deduplicate (array) {
const results = [];
const idCache = new Set();
for (const item of array) {
// skip if we've already seen products with the same ID
if (idCache.has(item.productId)) continue;
idCache.add(item.productId);
// get products with matching ID
const items = array.filter(({productId}) => productId === item.productId);
// if there were none, store the single product as-is and continue
if (items.length === 0) {
results.push({...item});
continue;
}
// add initial product to others, preserving order
items.unshift(item);
const merged = {};
for (const key of Object.keys(item)) {
const values = items.map(item => item[key]);
// if all the same value, set it on the merged object
if (values.every(val => val === item[key])) merged[key] = item[key];
else {
// set to property on obj in "options" array
for (const [idx, val] of values.entries()) {
((merged.options ??= [])[idx] ??= {})[key] = val;
}
}
}
results.push(merged);
}
return results;
}
const data = [
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "13inch",
optionPrice: 0,
qty: 2,
},
{
productId: 6,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "15inch",
optionPrice: 1000,
qty: 1,
},
{
productId: 5,
productName: "pouch",
productPrice: 29000,
discountRate: 19,
optionName: "15inch",
optionPrice: 1000,
qty: 1,
},
];
const result = deduplicate(data);
console.log(result);
Solution 3:[3]
Here is one way you can do it:
const data = [ { productId: 6, productName: "pouch", productPrice: 29000, discountRate: 19, optionName: "13inch", optionPrice: 0, qty: 2, }, { productId: 6, productName: "pouch", productPrice: 29000, discountRate: 19, optionName: "15inch", optionPrice: 1000, qty: 1, }, { productId: 4, productName: "pouch", productPrice: 29000, discountRate: 19, optionName: "15inch", optionPrice: 1000, qty: 1, }, ],
output = Object.entries(
data.reduce(
(prev,{productId,...r}) =>
({...prev, [productId]: Object.entries(r).reduce(
(acc,[key,value]) =>
({...acc, [key]: prev[productId] && prev[productId][key] ?
prev[productId][key] === value ?
value :
[prev[productId][key],value] :
value
}),{})
}),{}
)
)
.map(
([productId,obj]) =>
({
productId,
...Object.entries(obj).reduce(
(acc,[key,value]) =>
!Array.isArray(value) ?
({...acc, [key]:value}) :
({...acc, option:value.map(
(v,i) =>
acc["option"] ?
({...acc["option"][i], [key]: v}) :
({[key]: v}))
}),
{})
})
);
console.log(output);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | jsejcksn |
| Solution 3 | PeterKA |
