Filter items by highest attribute

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

What would be the best filtering that is repeated in the value of X, remaining the one with the highest value in Y?

    
asked by anonymous 04.06.2018 / 18:59

2 answers

2

Solution with sort and filter

A very compact solution is to use sort to sort the values all by name and y , with the highest y being the first.

Then use filter to filter in a way that whenever he picks up a repeated element from the previous element, he discards it. This works because because of sorting, the element you want to keep from repeating is always the first one.

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

No sort , when the names are equal with p1.x === p2.x makes the comparison and returns the one with the highest y with p2.y - p1.y . When they are different use name comparison through the localeCompare .

No filter holds 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 classic for and add if it does not exist or replace what already exists if you have y less:

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.

    
04.06.2018 / 19:46
0

Here's a way to do it:

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: link link

    
04.06.2018 / 20:12