1

Find a function ranking(people) which took an array of objects as input. Keys are: Name and Points. It should return a sorted array with the highest points on first position, the 2nd highest on second… It should ad a third key: Position. So far so good.

Problem: If two values of the same key are the same, then both objects should be placed on the same position.

Example:

ranking([{name: "John",points: 100},{ name: "Bob",points: 130},{name: "Mary", points: 120},{name: "Kate",points: 120}]);

Because Bob ranks highest, this objects should be returned at first. Mary and Kate are ranking at second. So both should be positioned at position: 2.

This is the part I am struggling with. My code so far (except the troubling part, which I put separated below)

function ranking(people) {
  people.sort((a, b) => (a.points > b.points ? -1 : 1));
  for (var i = 0; i < people.length; i++) {
    Object.assign(people[i], { position: i + 1 });
  }
  console.log(people);
}

I tried to compare the points keys in the for-Loop like

if(people[i].points === people[i+1].points) {
people[i+1].position === i;
}

which does not work. I think I need to use map or for…in , but I don't know how…

EDIT:

The output should be:

name: "Bob", points: 130, position: 1
name: "Kate", points: 120, position: 2
name: "Mary", points: 120, position: 2
name: "John", points: 100, position: 3 **NOT 4** 

After reading some of the hints I came up with:

   for (var j = 1; j < people.length; j++) {
     if (people[j - 1].points === people[j].points) {
       people[j].position = j;
     }
   }

But than is the problem, that there is no position 3 – just a position: 4

S.H
  • 671
  • 2
  • 6
  • 22
  • Why Mary and Kate will b returned if input is Bob – brk Mar 20 '19 at 15:11
  • 1
    Please have a look at my answer on another question about sorting: https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key/51725400#51725400 I'm sure that will help you. – Megajin Mar 20 '19 at 15:11
  • 1
    Turn your logic around. If people[i-1] does not exists, it's the first rank. If a previous person exists and the points are the same, the rank is the same as the previous person. Else its previous.points + 1. – Shilly Mar 20 '19 at 15:14

2 Answers2

1

var data = [{name: "John",points: 100},{ name: "Bob",points: 130},{name: "Mary", points: 120},{name: "Kate",points: 120}];

//Sorts the object array by the points key
data.sort( (currentItem, nextItem) => {
    return currentItem.points > nextItem.points ? -1 : 1;
});

//add in those positions by comparing each item to the one before
data.forEach( (item, index) => {

    item.position = index+1;
    if( 0 === index ){
        return;
    }
    
    let previousItem = data[index-1];
    item.position = previousItem.points === item.points ? previousItem.position : previousItem.position+1;
});


data.forEach( i => {
 console.log(i);
});
Craig Wayne
  • 4,499
  • 4
  • 35
  • 50
0

Keep two indices while iterating:

people.sort((a, b) => (a.points > b.points ? -1 : 1));

let position = 1;
for (var i = 0; i < people.length; i++) {
  Object.assign(people[i], { position });
  if(!i || people[i - 1].points > people[i].points) 
    position += 1;
}

return people;

Or if you want a oneliner:

people
  .sort((a, b) => a.points - b.points)
  .reduce((prev, curr) => (curr.position = prev.position + (curr.points < prev.points), curr), { position: 0, points: -Infinity });

return people;
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151