Filter elements by the highest attribute

Asked

Viewed 49 times

1

[
  {x:'Pedro', y:2},
  {x:'Lucas', y:3},
  {x:'Pedro', y:4}
]

Which would be the best filter that repeats at the value of X, remaining the one with the highest value in Y?

2 answers

2


Solution with sort and filter

A very compact solution is to use sort to sort all values by name and y, getting the bigger ones y first.

Then uses filter to filter so that whenever it picks up an element repeated to the previous one, it discards it. This works because due to ordering, the element you want to keep from repeaters is always the first.

Implementation:

let pessoas = [
  {x:'Pedro', y:2},
  {x:'Lucas', y:3},
  {x:'Pedro', y:4}
];

pessoas.sort((p1,p2) => p1.x === p2.x ? p2.y - p1.y : p1.x.localeCompare(p2.x));
let filtradas = pessoas.filter((el, idx) => idx === 0 || pessoas[idx - 1].x !== el.x);

console.log(filtradas);

In the sort, when the names are equal with p1.x === p2.x makes the comparison and returns what has larger y with p2.y - p1.y. When different uses the comparison of names through the locationCompare.

In the filter keeps the value if it is the first with idx === 0, or if the name is different from the previous one: pessoas[idx - 1].x !== el.x.

Solution with for classic and findIndex

You can also opt for a traditional solution with a for classic and add if there is no or replace the one that already exists if you have a y minor:

let pessoas = [
  {x:'Pedro', y:2},
  {x:'Lucas', y:3},
  {x:'Pedro', y:4}
];

let filtradas = [];
for (let i = 0; i < pessoas.length; ++i){
   let posPessoa = filtradas.findIndex(p => pessoas[i].x === p.x);
   if (posPessoa === -1){ //não existe
      filtradas.push(pessoas[i]); //adiciona
   }
   else if (filtradas[posPessoa].y < pessoas[i].y){ //existe e tem y menor
      filtradas[posPessoa] = pessoas[i]; //substitui pela de y maior
   }
}

console.log(filtradas);

In this solution the only native function I used was findIndex to find the position of the person with the same name in the array. This returns -1 if the element does not exist in the array.

0

Follow a way of doing:

function removeDuplicates(myArr, prop) {
    return myArr.filter((obj, pos, arr) => {
        return arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos;
    });
};

var lista = [
    { x: 'Pedro', y: 2 },
    { x: 'Lucas', y: 3 },
    { x: 'Pedro', y: 4 }
];
var listaX = removeDuplicates(lista, "x");
for (i = 0; i < listaX.length; i++) {
    var max = Math.max.apply(Math, lista.filter(function (e) { return e.x == listaX[i].x; }).map(function (o) { return o.y; }));
    var maxObj = lista.filter(function (e) { return e.x == listaX[i].x && e.y == max; });
    console.log(maxObj);
}

References: https://ilikekillnerds.com/2016/05/removing-duplicate-objects-array-property-name-javascript/ https://stackoverflow.com/questions/4020796/finding-the-max-value-of-an-attribute-in-an-array-of-objects

Browser other questions tagged

You are not signed in. Login or sign up in order to post.