Javascript 如何对包含表示分数的数组的多个对象进行排序?
给定如下对象数组:Javascript 如何对包含表示分数的数组的多个对象进行排序?,javascript,Javascript,给定如下对象数组: competitors = [{ name: "Alice", scores: [3,7,8,2,5] }, { name: "Bob", scores: [4,4,5,6,8] }, { name: "Carol", scores: [5,3,2,7,6] }]; 考虑到分数越低越好,我如何对它们进行排序(将它们排列为1-3级),以使优胜者是在每个指数中赢得最多比较的人 例如,对于Alice、Bob和Carol,Alice应
competitors = [{
name: "Alice",
scores: [3,7,8,2,5]
}, {
name: "Bob",
scores: [4,4,5,6,8]
}, {
name: "Carol",
scores: [5,3,2,7,6]
}];
考虑到分数越低越好,我如何对它们进行排序(将它们排列为1-3级),以使优胜者是在每个指数中赢得最多比较的人
例如,对于Alice、Bob和Carol,Alice应该赢,因为她赢了3场(3注:我更喜欢@Tibos答案,但这一场更简单 您可以使用排序函数():
功能getWins(竞争对手,竞争对手){
var得分=竞争对手得分;
var=0;
对于(变量i=0,n=scores.length;i得分[i]){
赢=假;
打破
}
}
}
如果(赢){
wins++;
}
}
回归胜利;
}
//根据竞争对手的获胜情况对其进行分类
竞争对手。排序(功能(a、b){
返回getWins(竞争对手,b)-getWins(竞争对手,a);
});
我发现它通常有助于将这样的大任务分解为几个阶段。我怀疑它是否有效,但它可能对您有用
首先:获取一个数组,其中包含每个竞争对手的结果:
function getScores() {
return competitors.map(function (el) {
return el.scores;
});
}
var scores = getScores();
然后拉出单个游戏信息:
function getGames(scores) {
var games = [];
for (var i = 0, l = scores[0].length; i < l; i++) {
games.push(scores.map(function (el) {
return el[i];
}));
}
return games;
}
var games = getGames(scores);
最后,更新每个竞争对手的结果
function applyWinners(winners) {
winners.forEach(function (el, i) {
var competitor = competitors[el];
if (!competitor.results) competitor.results = [];
competitor.results.push(i);
});
}
applyWinners(winners);
console.log(competitors) // Alice wins [0, 3, 4], Carol wins [1, 2]
一个特殊的比较功能,用于计算下一级别的比赛胜负,可以实现以下功能:
function compareArray(a, b) {
for (var i=0; i<a.length && i<b.length; i++)
if (a[i] != b[i])
return a[i] - b[i];
return a.length-b.length;
}
function addWins(c) {
var w = new Array(c.length);
for (var i=0; i<numJudges; i++) {
// if two players have scored equally, the first will win
var l = 0;
for (var j=1; j<c.length; j++)
if (c[j].scores[i] < c[l].scores[i])
l = j;
w[l] = (w[l]||0)+1;
}
for (var i=0; i<c.length; i++)
c[i].wins.push(w[i]||0);
}
for (var i=0; i<competitors.length; i++)
competitors[i].wins = [];
competitors.sort(function(a, b) {
var samelevel = competitors;
do {
var o = - compareArray(a.wins, b.wins)
if (o != 0)
return o;
var len = samelevel.length;
samelevel = samelevel.filter(function(c) {
return compareArray(c.wins, a.wins) == 0;
})
addWins(samelevel);
} while (samelevel.length < len);
return - compareArray(a.wins, b.wins);
});
函数比较数组(a,b){
对于(var i=0;iI会对项目的总和做些什么……这对你有什么启发吗?我已经在我的排名算法的前一步比较了分数总和。如果总和相等,我会继续进行这种平局打破(4个步骤中的最后一个)。如果两个竞争对手的分数相同(最低),会怎么样在某些游戏中得分?供将来参考:两对二比较不起作用,因为它允许循环排名:Alice:[1,2,3,4,5]Bob:[2,5,4,1,3]Carol:[5,1,2,3,4](由@DaveS给出的示例)如果我们比较两个竞争对手,那么就不会发生这种情况,因为在我的算法中,在这一点上,我处理的是每个竞争对手的分数为奇数。如果我们比较三个或更多的竞争对手,以及两个或更多的平局,那么我将不得不在平局的竞争对手集合上递归。如果竞争对手列表很长,这将变得非常缓慢,因为您将对每个比较执行(num scores*num competitors)操作…一个O(n^3)算法。@Pointy我不太关心速度,因为我实际上限制了分数数组的大小以及竞争对手的数量。这是排名算法的一部分,它通常会有奇数个分数(通常在3-11之间)和不超过20名竞争者。@Florent,这种类型(两对两比较)有一个问题是,在三个或三个以上的竞争对手中,可能会出现平局,如果将二乘二、二乘二和二乘二进行比较,就像在三方平局中一样,你可能会得到一个周期性的排名,如竞争对手#1>#2>#3>#1等。这看起来很有希望。当我有三个以上的竞争对手时,或者在ca中,我只需要重复几组竞争对手的胜负比如我的第二个例子,Dave、Eve和Frank,这是通过修改ApplyInners函数来实现递归的。
function findWinners(games) {
return games.map(function (el) {
return el.indexOf(Math.min.apply(null, el));
});
}
var winners = findWinners(games);
function applyWinners(winners) {
winners.forEach(function (el, i) {
var competitor = competitors[el];
if (!competitor.results) competitor.results = [];
competitor.results.push(i);
});
}
applyWinners(winners);
console.log(competitors) // Alice wins [0, 3, 4], Carol wins [1, 2]
function compareArray(a, b) {
for (var i=0; i<a.length && i<b.length; i++)
if (a[i] != b[i])
return a[i] - b[i];
return a.length-b.length;
}
function addWins(c) {
var w = new Array(c.length);
for (var i=0; i<numJudges; i++) {
// if two players have scored equally, the first will win
var l = 0;
for (var j=1; j<c.length; j++)
if (c[j].scores[i] < c[l].scores[i])
l = j;
w[l] = (w[l]||0)+1;
}
for (var i=0; i<c.length; i++)
c[i].wins.push(w[i]||0);
}
for (var i=0; i<competitors.length; i++)
competitors[i].wins = [];
competitors.sort(function(a, b) {
var samelevel = competitors;
do {
var o = - compareArray(a.wins, b.wins)
if (o != 0)
return o;
var len = samelevel.length;
samelevel = samelevel.filter(function(c) {
return compareArray(c.wins, a.wins) == 0;
})
addWins(samelevel);
} while (samelevel.length < len);
return - compareArray(a.wins, b.wins);
});