Tezz Chaudhary
Tezz Chaudhary

Reputation: 21

Remove duplicate from an array on a particular condition using jQuery

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

Upvotes: 1

Views: 566

Answers (4)

Sash Sinha
Sash Sinha

Reputation: 22360

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);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

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; }

Upvotes: 1

GonZo
GonZo

Reputation: 58

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);

Upvotes: 0

epascarello
epascarello

Reputation: 207501

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);

Upvotes: 4

Related Questions