将nums数组划分为2个平衡数组

时间:2017-05-12 21:13:15

标签: javascript arrays sorting

我采用的二维数组看起来像[[player1, 10], [player2, 8]]但有大约12名玩家。我对我听到的排序感到满意,除非采用这种方法,团队总是得到第一个选择"更好的球员。我正在努力想办法让teamB每隔一段时间给予更好的球员。以下是适用的代码"足够好"。

data = [["player1", 10]. ["player2", 8], ["player3", 7], ["player4", 9]];
var teamA = [];
var teamB = [];

var remaining = [];

for (item in data) {
  remaining.push(data[item].slice());
}

for (i in data) {
  var max = 0;
  var selection = [,];
  var index = -1;

  for (k in remaining) {
    if (remaining[k][1] > max) {
      selection =  remaining[k];
      max = remaining[k][1];
      index = k;
    }
  }
  remaining.splice(index, 1);

  if (i % 2 == 0) {
    teamA.push(selection);
  } else {
    teamB.push(selection);
  }
}

这导致teamA: [["player1, 10],["player2", 8]]teamB: [["player4", 9],["player3", 7]] 我更喜欢的是player2和player3切换团队。这是我尝试过的。

// inside my first for loop
if (3 % i == 0) {
  i++;
} else if (4 % i == 0) {
  i--;
}

在我的大脑中,这应该运作得很好,但哇没有做到!我最终在teamB上有9名球员,在teamA上有3名球员。我摆弄着这种方法的不同变化而没有运气。

任何指针?

编辑:为了澄清,可以假设数据集将是未分类的,并且数据集的长度将始终是偶数。不会成为一支拥有更多球员的球队。

2 个答案:

答案 0 :(得分:0)

我已经编辑了你的代码,以便它首先为teamA选择,然后它将为teamB选择2,然后为teamA选择2,依此类推。

var data = [
    ["player1", 10],
    ["player2", 8],
    ["player3", 7],
    ["player4", 9],
    ["player5", 5],
    ["player6", 6]
];
var teamA = [];
var teamB = [];

var remaining = [];

for (item in data) {
    remaining.push(data[item].slice());
}

var turnA = false;
var counterA = 0,
    counterB = 0;
for (i in data) {
    var max = 0;
    var selection = [, ];
    var index = -1;

    for (k in remaining) {
        if (remaining[k][1] > max) {
            selection = remaining[k];
            max = remaining[k][1];
            index = k;
        }
    }
    remaining.splice(index, 1);

    // add first player to teamA and continue
    if (i == 0) {
        teamA.push(selection);
        continue;
    }

    if (turnA) {
        teamA.push(selection);
        counterA++;
    } else {
        teamB.push(selection);
        counterB++;
    }

    if (turnA && counterA == 2) {
        counterA = 0;
        turnA = false;
    } else if (!turnA && counterB == 2) {
        counterB = 0;
        turnA = true;
    }
}

答案 1 :(得分:0)

因此,您要采取的策略是分区问题,如下所述:https://en.wikipedia.org/wiki/Partition_problem

你基本上想要根据球员和球员的总和来计算两支球队的总和。得分,比较总和,并将当前球员分配给得分较低的球队。

首先,我们对玩家数据进行排序。

在第一次传球时,我们随机选择一支球队来分配最佳球员。在遍历播放器池的其余部分时,我们遵循分区问题中描述的算法。

作为分区问题的一个例子,我写了一些非常快的内容:https://codepen.io/thenormalsquid/pen/Lymjbb?editors=0001

// stack overflow answer


var data = [["player1", 10], ["player2", 8], ["player3", 7], ["player4", 9]];
var teamA = [];
var teamB = [];
var selectionProbability = 0.5;

var remaining = [];

data.sort(function(playerA, playerB){
    if(playerA[1] < playerB[1]) {
    return 1;
  }

  if(playerA[1] > playerB[1]) {
    return -1;
  }

  return 0;
});

var sum = function(team) {
  if (team.length === 0) {
    return 0;
  }
  var i,
      s = 0;
  for(i = 0; i < team.length; i++) {
    s += team[i][1];
  }
  return s;
};

var chooseTeam = function() {
  if(Math.random() < selectionProbability) {
    return 'teamA';
  }
  return 'teamB';
};


function assignTeams() {
  var i;
  for(i = 0; i < data.length; i++) {
    var sumA = sum(teamA),
        sumB = sum(teamB);
    // first pass, we'll have a 50/50 chance 
    // of placing the best player in either team A or team B

    if (i === 0) {
      var chosenTeam = chooseTeam();
      if (chosenTeam === 'teamA') {
        teamA.push(data[i]);
      } else {
        teamB.push(data[i]);
      }
    } else if (sumA < sumB) {
      teamA.push(data[i]);
    } else {
      teamB.push(data[i]);
    }
  }
}

function addPlayerToHtml(player, teamId) {
  var li = document.createElement('li'),
      text = document.createTextNode(player[0] + ' ' + player[1]);
  li.appendChild(text);
  document.getElementById(teamId).appendChild(li);
}

var button = document.getElementById('assignPlayers');
button.addEventListener('click', function(){
  assignTeams();

  teamA.forEach(function(player){
    addPlayerToHtml(player, 'teamA');
  });

  teamB.forEach(function(player){
    addPlayerToHtml(player, 'teamB');
  });

});