I have the following two arrays:
var oldOrder = [{"Id": "10","Qty": 1}, {"Id": "3","Qty": 2}, {"Id": "9","Qty": 2}]; var newOrder = [{"Id": "5","Qty": 2},{"Id": "10","Qty": 3}, {"Id": "9","Qty": 1}];
I need to end up with a newArray containing only one object per Id, but if the ids in an object in the oldOrder array and newOrder array then I need to get the difference in the Qty positive or negative. So for example the above would create this new array:
var newArray = [{"Id": "5","Qty": 2},{"Id": "10","Qty": 2}, {"Id": "9","Qty": -1}];
I would also like to get the dropped orders that are present in the oldOrder Array but not in the newOrder array:
var droppedOrders = [{"Id": "3","Qty": 2}];
I have already got this logic for getting the dropped orders but I am struggling with creating the newArray and tying the logic into the same function if possible?
function comparer(otherArray){ return function(current){ var onlyInOld = otherArray.filter(function(other){ return other.Id == current.Id; }).length == 0; return onlyInOld; } } var droppedOrders= oldOrder.filter(comparer(newOrder)); console.log(droppedOrders);
Edited to add that I cannot use ESC6 features like spread or fat arrow etc.
Advertisement
Answer
You can easily achieve the result using Map
1) Using ES6
var oldOrder = [ { Id: "10", Qty: 1 }, { Id: "3", Qty: 2 }, { Id: "9", Qty: 2 }, ]; var newOrder = [ { Id: "5", Qty: 2 }, { Id: "10", Qty: 3 }, { Id: "9", Qty: 1 }, ]; const oldMap = new Map(oldOrder.map((o) => [o.Id, o])); const newMap = new Map(newOrder.map((o) => [o.Id, o])); const result = newOrder.map((o) => oldMap.has(o.Id) ? { ...o, Qty: o.Qty - oldMap.get(o.Id).Qty } : o ); const droppedOrders = oldOrder.filter(({ Id }) => !newMap.has(Id)); console.log(result); console.log(droppedOrders);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0; }
2) Using ES5
var oldOrder = [ { Id: "10", Qty: 1 }, { Id: "3", Qty: 2 }, { Id: "9", Qty: 2 }, ]; var newOrder = [ { Id: "5", Qty: 2 }, { Id: "10", Qty: 3 }, { Id: "9", Qty: 1 }, ]; const oldMap = {}; const newMap = {}; oldOrder.forEach(function (o) { oldMap[o.Id] = o; }); newOrder.forEach(function (o) { newMap[o.Id] = o; }); const result = newOrder.map(function (o) { return oldMap[o.Id] ? Object.assign({}, o, { Qty: o.Qty - oldMap[o.Id].Qty }) : o; }); const droppedOrders = oldOrder.filter(function (o) { return !newMap[o.Id]; }); console.log(result); console.log(droppedOrders);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0; }