javascript - 在 Javascript 中按值给出一系列目标的排名分数

标签 javascript arrays sorting

/*
Given an array of objects: ID|userName|totalScore|competitionRank,
number ID
string userName
number totalScore
number competitionRank
all competitionRanks are set to NULL
give each score a ranking in descending order
*/

我目前不确定这是否会通过所有边缘情况。另外,这似乎是我能做到的最快的,任何改进方面的帮助都会很棒。它通过了我能想到的测试用例。任何帮助将不胜感激。

//Initialize data structure
var playerScores = [
  {
    "ID": 1,
    "userName": "person1",
    "totalScore": 230,
    "competitionRank": null
  },{
    "ID": 2,
    "userName": "person2",
    "totalScore": 220,
    "competitionRank": null
  },{
    "ID":3,
    "userName": "person3",
    "totalScore": 250,
    "competitionRank": null
  },{
    "ID":4,
    "userName": "person4",
    "totalScore": 230,
    "competitionRank": null
  },{
    "ID": 5,
    "userName": "person5",
    "totalScore": 250,
    "competitionRank": null
  }
];

playerScores.sort(function(a,b){
  return b.totalScore - a.totalScore;
});

var numTies = 0;
playerScores[0].rank = 1;
for (i = 1; i < playerScores.length; i++){
  if (playerScores[i].totalScore === playerScores[i-1].totalScore){
    numTies++;
    playerScores[i].rank = playerScores[i-1].rank;
  }
  else{
    playerScores[i].rank = i+numTies;
    numTies = 0;
  }
 }

console.log(playerScores);

最佳答案

我相信您当前的代码i + numTies实际上应该是i + numTies + 1,因为数组索引(i)是从零开始,但排名从 1 开始(对于问题中的测试数据,这不会导致问题,因为唯一的非绑定(bind)项是最后一个)。

但是您根本不需要 numTies 变量,因为非绑定(bind)元素的排名始终与其在数组中的位置相同 (+1)。

此外,如果数组为空,执行第一项的 for 循环之前的行将给出错误,因此您应该对此进行测试。并使用 var 声明 i:

var playerScores = [
  { "ID": 1, "userName": "person1", "totalScore": 230, "competitionRank": null },
  { "ID": 2, "userName": "person2", "totalScore": 220, "competitionRank": null },
  { "ID": 3, "userName": "person3", "totalScore": 250, "competitionRank": null },
  { "ID": 4, "userName": "person4", "totalScore": 230, "competitionRank": null },
  { "ID": 5, "userName": "person5", "totalScore": 250, "competitionRank": null }
];

playerScores.sort(function(a,b){ return b.totalScore - a.totalScore; });

if (playerScores[0]) playerScores[0].rank = 1;
for (var i = 1; i < playerScores.length; i++) {
  if (playerScores[i].totalScore === playerScores[i-1].totalScore) {
    playerScores[i].rank = playerScores[i-1].rank;
  } else {
    playerScores[i].rank = i + 1;
  }
}

console.log(playerScores);

如果您从 0 而不是 1 开始循环,并测试循环内的第一个元素,那么您可以选择重构代码以使用数组迭代函数而不是 for循环 - 执行速度较慢,但​​(可以说)更易于阅读。

为了多样化,我使用了三元运算符而不是 if/else:

var playerScores = [
  { "ID": 1, "userName": "person1", "totalScore": 230, "competitionRank": null },
  { "ID": 2, "userName": "person2", "totalScore": 220, "competitionRank": null },
  { "ID": 3, "userName": "person3", "totalScore": 250, "competitionRank": null },
  { "ID": 4, "userName": "person4", "totalScore": 230, "competitionRank": null },
  { "ID": 5, "userName": "person5", "totalScore": 250, "competitionRank": null }
];

playerScores.sort(function(a,b){ return b.totalScore - a.totalScore; });

playerScores.forEach(function(player, i, arr) {
  player.rank = i === 0 || player.totalScore != arr[i-1].totalScore
              ? i + 1
              : arr[i-1].rank;
});

console.log(playerScores);

关于javascript - 在 Javascript 中按值给出一系列目标的排名分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44916692/

相关文章:

java - 旋转线扫描 - 排序边缘

javascript - 在 JavaScript 中排序 : Should every compare function have a "return 0" statement?

javascript - ES6 将整个对象解构为 this

javascript - ejs中的if语句

javascript - JQuery Change 类在 Div Clicked 最近的 "i"

c++ - 比较 char[] 和 char*

java - 简单的 OOP/私有(private)变量查询 - Java

c - 如何在 C 中声明和初始化 4 维数组

javascript - 如何使用 jQuery 将焦点设置到 CKEditor 5?

在 haskell 中对列表的列表进行排序