You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JavaScript生成9组各含5场无重复赛事的比赛日方案求助

问题

我有一个包含45项赛事的数组,每项赛事包含主队(local)和客队(visitor)两支队伍。需要编写一个函数,生成9个比赛日,每个比赛日包含5场赛事,且所有赛事不可重复。

我尝试了以下代码:

const getRandomGame = (items, idsToAvoid) => {
  const game = getRandomFromArray(items);

  if (idsToAvoid.includes(game[0].id, game[1].id))
    return getRandomGame(items, idsToAvoid);

  return game;
};

const getRandomFromArray = (items) => {
  return items[Math.floor(Math.random() * items.length)];
};


// 这段代码在生成比赛日的函数内部
for (let i = 0; i < 9; i++) {
    counter++;
    let games = [];
    let avoidIds = [];

    for (let j = 0; j < 5; j++) {
      const game = getRandomGame(copyFinalGames, avoidIds);

      const localRng = Math.random() < 0.5;
      const local = localRng ? game[0] : game[1];
      const visitor = localRng ? game[1] : game[0];

      avoidIds.push(local.id, visitor.id);

      games.push({
        id: counter,
        local,
        visitor,
      });

      copyFinalGames = copyFinalGames.filter(
        (item) => !(item[0].id === game[0].id && item[1].id === game[1].id)
      );
    }

    gamedays.push({
      id: i + 1,
      games,
    });
  }

但这个方案存在赛事重复的问题,而且用暴力方式规避重复,效率很低。请问有什么优化方案?

原数组示例如下:

[
  [{ id: 1 }, { id: 2}],
  [{ id: 3 }, { id: 4}],
  [{ id: 5 }, { id: 6}] 
  // 实际包含45组这样的赛事组合
]

优化方案

核心思路

  • 先洗牌再分组:用高效的Fisher-Yates洗牌算法打乱所有赛事,避免反复随机选取的低效操作
  • 批量分割:将打乱后的赛事按每5个一组直接分割,正好得到9个比赛日,天然保证赛事不重复
  • 随机主客场:对每个赛事单独随机分配主客场,保留原需求的随机性

优化后的代码

// Fisher-Yates洗牌算法,高效打乱数组
const shuffleArray = (array) => {
  const newArray = [...array];
  for (let i = newArray.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [newArray[i], newArray[j]] = [newArray[j], newArray[i]];
  }
  return newArray;
};

const generateMatchdays = (allGames) => {
  // 1. 打乱所有赛事顺序
  const shuffledGames = shuffleArray(allGames);
  const gamedays = [];
  let counter = 0;

  // 2. 每5个赛事为一个比赛日
  for (let i = 0; i < shuffledGames.length; i += 5) {
    const dayGames = shuffledGames.slice(i, i + 5).map(game => {
      counter++;
      // 随机决定主客场
      const isLocalFirst = Math.random() < 0.5;
      return {
        id: counter,
        local: isLocalFirst ? game[0] : game[1],
        visitor: isLocalFirst ? game[1] : game[0]
      };
    });

    gamedays.push({
      id: gamedays.length + 1,
      games: dayGames
    });
  }

  return gamedays;
};

// 使用示例
// const allGames = [/* 你的45项赛事数组 */];
// const matchdays = generateMatchdays(allGames);

方案优势

  • 彻底解决重复问题:所有赛事只被分配一次,不存在重复选取的可能
  • 效率大幅提升:洗牌和分组的时间复杂度均为O(n),避免了原方案中递归重试和频繁过滤数组的低效操作
  • 逻辑简洁易维护:去掉了复杂的avoidIds校验和递归逻辑,代码可读性更高

内容的提问来源于stack exchange,提问作者nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 20:05:27