2

我有一个对象数组,它们有一个键值对,如下所示。

    players=[
             {
                id : 1,
              name : "player1", 
             value : 5.6, 
          position : "Goalkeeper"
             },{
                id : 1,
              name : "player1", 
             value : 7.7, 
          position : "Defender"
             },{
                id : 1,
              name : "player2", 
             value : 6.1, 
          position : "Midfielder"
             },{
                id : 1,
              name : "player1", 
             value : 7.2, 
          position : "Forward"
             },.....n ]

我想要实现的是从 700 名球员的阵列中自动选择 15 名球员,其中守门员应该是 2 名、5 名后卫、5 名中场球员和 3 名前锋,以使他们的总价值接近或等于 100 。任何帮助,将不胜感激 :-)

4

1 回答 1

1

首先将玩家分成各自的位置:

const getPosition = (arr, pos) => arr.filter(({position}) => position === pos);

然后使用一种方法将这些数组组合成一个指定长度的数组,尝试所有组合:

function combinations(arr, length) {
  function* walk(start, depth) {
    for(let i = start; i < arr.length; i++) {
      if(depth) {
        for(const combo of walk(i + 1, depth - 1)) {
           yield [...combo, arr[i]];
        }
      } else {
         yield [arr[i]];
      }
    }
  }
  return walk(0, length);
}

现在要获得所有不同的团队,我们可以像这样组合它们:

 function* compose(iterator, ...iterators) {
    for(const value of iterator) {
      if(iterators.length) {
        for(const combo of compose(...iterators)) {
           yield [value, ...combo];
        }
      } else {
        yield [value];
      }
   }
}

const teams = compose(
  combinations(getPosition("Goalkeeper"), 3),
  combinations(getPosition("Defender"), 5),
  combinations(getPosition("Midfielder"), 5),
  combinations(getPosition("Forward"), 3)
);

现在我们只需要找到最好的团队:

const distance = team => Math.abs(team.reduce((score, player) => score + player.value, 0) - 100);

let best = teams.next().value;

for(const team of teams) {
  if(distance(best) > distance(team)) 
    best = team;
  if(!distance(best)) break;
}
于 2018-06-17T10:41:31.953 回答