1

I have an array like this:

var SOItems = [
  { ID: "10", RevNo: 0 },
  { ID: "11", RevNo: 0 },
  { ID: "10", RevNo: 1 },
  { ID: "10", RevNo: 2 },
  { ID: "12", RevNo: 0 },
  { ID: "12", RevNo: 1 }
]; 

I have gone through Remove Duplicate and Get Unique and it works but not as expected because it returns the first matching value. I want those unique items whose RevNo is greater like:

SOItems = [
  { ID: "11", RevNo: 0 },
  { ID: "10", RevNo: 2 },
  { ID: "12", RevNo: 1 }
];

Please suggest me a solution

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339

4 Answers4

4

I would use reduce which will kep track of the ids. If it has seen it, look for the rev number that is greater. After reduce is done, use Object.values() to return it to the array of objects.

var SOItems = [{ID:"10",RevNo:0},{ID:"11",RevNo:0},{ID:"10",RevNo:1},{ID:"10",RevNo:2},{ID:"12",RevNo:0},{ID:"12",RevNo:1}]; 

var result = Object.values(SOItems.reduce( function (acc, item) {
  var last = acc[item.ID];
  if (!last || item.RevNo > last.RevNo) {
    acc[item.ID] = item;
  }
  return acc;
}, {}));

console.log(result);
epascarello
  • 204,599
  • 20
  • 195
  • 236
1

You could take an object for keeping the index fro the object with the highest RevNo. Then sort the indices to maintain the original order and map with the objects.

const
    items = [{ ID: "10", RevNo: 0 }, { ID: "11", RevNo: 0 }, { ID: "10", RevNo: 1 }, { ID: "10", RevNo: 2 }, { ID: "12", RevNo: 0 }, { ID: "12", RevNo: 1 }],
    result = Object
        .values(items.reduce((r, o, i, a) => {
            if (!(o.ID in r) || a[r[o.ID]].RevNo < o.RevNo) r[o.ID] = i;
            return r;
        }, {}))
        .sort((a, b) => a - b)
        .map(i => items[i]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You could use a Map for O(n) time complexity:

const SOItems = [
  { ID: "10", RevNo: 0 },
  { ID: "11", RevNo: 0 },
  { ID: "10", RevNo: 1 },
  { ID: "10", RevNo: 2 },
  { ID: "12", RevNo: 0 },
  { ID: "12", RevNo: 1 },
];
// console.log(SOItems);

const IDToItemWithMaxRevNo = new Map();
for (const item of SOItems) {
  if (
    IDToItemWithMaxRevNo.has(item.ID) &&
    IDToItemWithMaxRevNo.get(item.ID).RevNo < item.RevNo
  ) {
    IDToItemWithMaxRevNo.set(item.ID, item);
  } else {
    IDToItemWithMaxRevNo.set(item.ID, item);
  }
}
// console.log(IDToItemWithMaxRevNo);

const SOItemsNoDuplicates = Array.from(IDToItemWithMaxRevNo.values());
console.log(SOItemsNoDuplicates);
Sash Sinha
  • 18,743
  • 3
  • 23
  • 40
0

You can loop through your data and assemble a clean array using ID as key

let SOItems_selected = new Array();
for (let index = 0; index < SOItems.length; index++) {
    let item = SOItems[index];
    if ('undefined' == typeof(SOItems_selected[item.ID])) { // this particular ID hasn't been copied over the clean array
        SOItems_selected[item.ID] = item;
        continue;
    }
    if (item.RevNo > SOItems_selected[item.ID].RevNo) { // this particular item has a higher value for RevNo so it overwrites the existing item
        SOItems_selected[item.ID] = item;
        continue;
    }
}

console.log(SOItems_selected);
GonZo
  • 58
  • 5