Removing duplicate objects in an array, keeping values ​​with the maximum property value

I have an array like this:

const array=[ {id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4} ]

      

My goal should be like this:

const array=[ {id:1, quantity:2}, {id:0, quantity:4} ]

      

The order of the object doesn't matter as long as it can find "id" with a lot

I tried filter + findIndex, map + filter, etc., but I kept making the error. I need help.

+3


source to share


4 answers


You can use a hash table and check if the object with the same is id

in the result set. If the actual quantity is higher, assign the actual object.



var array = [{ id: 0, quantity: 1 }, { id: 1, quantity: 2 }, { id: 0, quantity: 4 }],
    hash = Object.create(null),
    unique = array.reduce(function (r, o) {
        if (!(o.id in hash)) {
            hash[o.id] = r.push(o) - 1;
            return r;
        }
        if (o.quantity > r[hash[o.id]].quantity) {
            r[hash[o.id]] = o;
        }
        return r;
    }, []);
    
console.log(unique);
      

.as-console-wrapper { max-height: 100% !important; top: 0; }
      

Run codeHide result


+4


source


Here you go.



const array=[ {id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4} ];

const arrayFiltered = [];

array.forEach(obj => {
    const item = arrayFiltered.find(thisItem => thisItem.id === obj.id);
    if (item) {
        if (item.quantity < obj.quantity) {
            item.quantity = obj.quantity;
        }
        
        return;
    }
    
    arrayFiltered.push(obj);
});

console.log(arrayFiltered);
      

Run codeHide result


+1


source


Can you work with objects? There's a simple alternative using this code

const array = [{id:0, quantity:1}, {id:1, quantity:2}, {id:0, quantity:4}]
const object = {}
array.forEach((element) => {
  object[element.id] = element
})

      

The only problem is that you will be overriding the previous element every time you find an element with the same ID.

0


source


Let all the identifiers first. Then, for each unique id, we will find all matching objects in the array (using filter

) and get the maximum of all our properties quantity

.

function uniqByMax(arr) {
  const ids = arr.map(elt => elt.id);
  const uniqueIds = uniq(ids);

  return uniqueIds.map(id => {
    const matchingElts = arr.filter(elt => elt.id === id);
    const quantities = matchingElts.map(elt => elt.quantity);
    const quantity = Math.max(...quantities);

    return {id, quantity};
  });
}

      

You can grab uniq

from the net anywhere, or use a library, or write it yourself.

Here's another approach that uses a side effect filter if it's your cup of tea:

function uniqByMax(arr) {
  return arr.filter(elt => {
    const previous = arr.find(e2 => e2.id === elt.id);
    if (previous === elt) return true;
    previous.quantity = Math.max(previous.quantity, elt.quantity);
  });
}

      

The basic idea is to iterate over the elements. For each element, we find if there is an earlier element with the same ID. If not, keep this element ( return true;

); otherwise, update the quantity of the previously saved item with the maximum quantity and this value of that item.

In the interest of generality, it might be interesting to parameterize this function with a property that we find unique values ​​and a way to update / combine multiple elements:

function uniqTransform(arr, prop, combine) {
  return arr.filter(elt => {
    const previous = arr.find(e2 => e2[prop] === elt[prop]);
    if (previous === elt) return true;
    combine(previous, elt);
  });

      

Then we call it with

uniqTransform(arr, 'id', (a, b) => a.quantity = Math.max(a.quantity, b.quantity));

      

Or we could generalize it further by using another function to identify elements that are to be considered the same for identification purposes, which we will call uniqueFunc

:

function uniqTransform(arr, uniqueFunc, combineFunc) {
  return arr.filter(elt => {
    const previous = arr.find(e2 => uniqueFunc(elt, e2));
    if (previous === elt) return true;
    combineFunc(previous, elt);
  });

      

Then we call it with

uniqTransform(
  arr, 
  (a, b) => a.id === b.id, 
  (a, b) => a.quantity = Math.max(a.quantity, b.quantity));

      

0


source







All Articles