I am trying to merge duplicate values if more than one same fields are exists in another object.
In below example - I have multiple objects of same asset_id and event_code which is repeated so I need to keep one and merge their value. I tried to do that but not getting the proper solution and output for the same.
const transaction = [{
value: 5,
asset_id: 'ABC',
event_code : 1
}, {
value: 15,
asset_id: 'HGF',
event_code : 1
}, {
value: 15,
asset_id: 'XYZ',
event_code : 2
}, {
value: 20,
asset_id: 'XYZ',
event_code : 2
}, {
value: 25,
asset_id: 'DEF',
event_code : 3
}, {
value: 20,
asset_id: 'HGF',
event_code : 3
}, {
value: 20,
asset_id: 'HGF',
event_code : 3
},
{
value: 10,
asset_id: 'ABC',
event_code : 1
}];
let newArr = [];
transaction.forEach(function (obj, ind, arr) {
if (ind === arr.length - 1 || obj.asset_id !== arr[ind 1].asset_id && obj.event_code!== arr[ind 1].event_code) {
newArr.push(obj);
} else {
arr[ind 1].value = obj.value;
}
});
console.log(newArr)
Expected Output Should be like this :
[{
value: 15,
asset_id: 'ABC',
event_code: 1
}, {
value: 15,
asset_id: 'HGF',
event_code: 1
}, {
value: 35,
asset_id: 'XYZ',
event_code: 2
} {
value: 25,
asset_id: 'DEF',
event_code: 3
}, {
value: 40,
asset_id: 'HGF',
event_code: 3
}]
CodePudding user response:
here is the solution for you
const arr = [{
value: 5,
asset_id: 'ABC',
event_code : 1
}, {
value: 15,
asset_id: 'HGF',
event_code : 1
}, {
value: 15,
asset_id: 'XYZ',
event_code : 2
}, {
value: 20,
asset_id: 'XYZ',
event_code : 2
}, {
value: 25,
asset_id: 'DEF',
event_code : 3
}, {
value: 20,
asset_id: 'HGF',
event_code : 3
}, {
value: 20,
asset_id: 'HGF',
event_code : 3
},
{
value: 10,
asset_id: 'ABC',
event_code : 1
}];
const fun = (ar)=>{
const output = ar.reduce((prev, curr) => {
const tmp = prev.find(e => e.asset_id===curr.asset_id);
if (tmp) {
tmp.value = curr.value tmp.value;
} else {
prev.push({
asset_id: curr.asset_id,
event_code: curr.event_code,
value : curr.value
});
}
return prev;
}, []);
return output
}
console.log(fun(arr))
CodePudding user response:
Here's one approach. We:
Build a map-of-maps, keyed by
asset_id
- Whose values are maps, keyed by
event_code
- Whose values are lists of transactions
sharing a common
asset_id
andevent_code
- Whose values are lists of transactions
sharing a common
function buildMapOfMaps( transactionList ) { const mapOfMaps = new Map(); for (const t of transactionList ) { let map = mapOfMaps.get( t.asset_id ); if !map { map = new Map(); mapOfMaps.set(t.asset_id,map); } let transactions = map.get( t.event_code ); if (!transactions) { transactions = []; m.set( t.event_code, transactions ); } transactions.push( t ); } return mapOfMaps; }
- Whose values are maps, keyed by
Once we have that, we iterate over the map-of-maps, and roll up those transactions sharing a common
asset_id
andevent_code
into a single transactionfunction rollUpCommonTransactions( mapOfMaps ) { const rollup = []; for ( const map of mapOfMaps.values() ) { for ( const transactions of map.values() ) { const summary = transactions.reduce( (x,y) => { x.value = y.value; return x; }); rollup.push(summary); } } return rollup; }
Then it's just a matter of putting it all together:
function mergeTransactions( transactionList ) {
const mapOfMaps = buildMapOfMaps(transactionList)
const rollup = rollUpCommonTransactions(mapOfMaps);
return rollup;
}
CodePudding user response:
You're on the right track but, rather than be concerned about the next element:
- See if you can
Array#
find the current element (sameasset_id
andevent_code
) innewArr
- If found, just increment the found element's value by
obj.value
- And if not found, add the current element to
newArr
You could as well use Array#findIndex
- (index)
in which case old = newArr[index]
const transaction = [{ value: 5, asset_id: 'ABC', event_code : 1 }, { value: 15, asset_id: 'HGF', event_code : 1 }, { value: 15, asset_id: 'XYZ', event_code : 2 }, { value: 20, asset_id: 'XYZ', event_code : 2 }, { value: 25, asset_id: 'DEF', event_code : 3 }, { value: 20, asset_id: 'HGF', event_code : 3 }, { value: 20, asset_id: 'HGF', event_code : 3 }, { value: 10, asset_id: 'ABC', event_code : 1 }];
let newArr = [];
transaction.forEach(function (obj) {
const old = newArr.find(
({asset_id,event_code}) =>
asset_id === obj.asset_id && event_code === obj.event_code
);
if (old) {
old.value = obj.value;
} else {
newArr.push(obj);
}
});
console.log(newArr)