如何对包含表示分数的数组的多个对象进行排序?

时间:2014-03-03 15:30:38

标签: 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),以便获胜者是赢得每个指数中最多比较的人?

例如,对于爱丽丝,鲍勃和卡罗尔,爱丽丝应该获胜,因为她在可能的5中有3胜(3 <4 <5,2 <6 <7,5 <6 <8)。

更复杂的例子是

competitors = [{
    name: "Dave",
    scores: [8,1,1,8,4]
}, {
    name: "Eve",
    scores: [1,5,4,5,2]
}, {
    name: "Frank",
    scores: [6,2,3,4,7]
}];

此处,弗兰克输掉(1胜:4 <5 <8),而戴夫(2胜:1 <2 <5,1 <3 <4)和夏娃(2胜:1 <6 <8,2 <2) 4&lt; 7)领带。所以只用戴夫和夏娃重复这个过程,你可以打破平局。伊芙以3胜2负的成绩赢得决胜局。最后的排名是夏娃,戴夫,弗兰克。

我会提前知道每个参赛者的得分数(让我们称之为 numJudges ),以及可能得分的范围(让我们称之为1- numCompetitors < / em>的)。我也不关心浏览器支持,除了webkit的javascript引擎,所以这意味着支持ECMAScript 5和一些6(es5-compat-table),比如数组函数每个地图过滤缩小

3 个答案:

答案 0 :(得分:1)

我发现它经常有助于将这样的大任务分成几个阶段。我怀疑它是否有效,但它可能对你有用。

开始:获取一个包含每个竞争对手结果的数组:

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 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]

Fiddle

答案 1 :(得分:0)

注意:我更喜欢@Tibos答案,但这个更简单

您可以使用排序功能(Array.sort):

function getWins(competitors, competitor) {
  var scores = competitor.scores;
  var wins = 0;

  for (var i = 0, n = scores.length; i < n; i++) {
    var win = true;

    for (var j = 0, m = competitors.length; j < m; j++) {
      // Do not compare the competitor with himself
      if (competitors[j] !== competitor) {
        // Do not count a win if someone beat him
        if (competitors[j].scores[i] > scores[i]) {
          win = false;
          break;
        }
      }
    }

    if (win) {
      wins++;
    }
  }

  return wins;
}

// Sort competitors according to their wins
competitors.sort(function(a, b) {
  return getWins(competitors, b) - getWins(competitors, a);
});

答案 2 :(得分:0)

一个特殊的比较函数可以计算下一关系的胜利,可以这样做:

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