为Secret Santa应用添加配对排除条件的实现问题
解决方案
要实现John与Martha互斥配对的需求,核心是添加配对校验逻辑,一旦生成的配对违反规则就重新生成,直到得到符合要求的结果。具体实现如下:
关键修改点
- 定义明确的禁止配对规则,覆盖John→Martha和Martha→John两种情况
- 封装循环生成配对的逻辑,直到校验通过
- 优化洗牌函数,避免修改原数组
修改后的完整代码:
function App() { const names = ["John", "Martha", "Adam", "Jane", "Michael"]; // 定义需要排除的配对组合 const forbiddenPairs = [ { santa: "John", receiver: "Martha" }, { santa: "Martha", receiver: "John" } ]; const shuffle = (arr: string[]) => { // 复制原数组,避免修改原始数据 const shuffledArr = [...arr]; for (let i = shuffledArr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffledArr[i], shuffledArr[j]] = [shuffledArr[j], shuffledArr[i]]; } return shuffledArr; }; // 生成符合规则的配对 const generateValidMatches = () => { let validMatches = null; while (!validMatches) { const randomNames = shuffle(names); const matches = randomNames.map((name, index) => ({ santa: name, receiver: randomNames[index + 1] || randomNames[0] })); // 检查是否存在违规配对 const hasInvalidPair = matches.some(match => forbiddenPairs.some(forbidden => forbidden.santa === match.santa && forbidden.receiver === match.receiver ) ); if (!hasInvalidPair) { validMatches = matches; } } return validMatches; }; const matches = generateValidMatches(); return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p>Secret santa game</p> <select> <option>Select your name...</option> {names.map((name) => ( <option key={name}> {name}</option> ))} </select> <div> {matches.map((match, index) => ( <div key={index}> {match.receiver}, {match.santa} <br /> </div> ))} </div> </header> </div> ); } export default App;
代码说明
- 禁止配对规则:用
forbiddenPairs数组存储需要排除的配对,后续如果要添加其他互斥组合,直接在数组里新增即可。 - 洗牌优化:通过
[...arr]复制原数组,避免洗牌操作修改原始的names数组。 - 循环校验逻辑:
generateValidMatches函数会不断生成新的配对,直到没有违规情况出现才返回结果,确保最终配对符合要求。 - React规范优化:为列表元素添加
key属性,符合React列表渲染的性能要求。
内容的提问来源于stack exchange,提问作者Kasia
相关产品推荐
相关产品推荐

