Ulq*_*fer 6 javascript algorithm
我正在创建一个匹配功能,将 2 个体重相同的玩家配对。
目前它正在基于相同的重量工作。现在,我的目标是为每场比赛添加一个序列。例如。
*如果玩家 1参加了第 1 场比赛,那么玩家 1 的下一场比赛应该是第 4 场或第 6 场比赛。玩家的每场比赛应该至少有 3 个、最多 6 个间隙,然后才能再次匹配该特定玩家。
我在下面提供了当前的输出和目标输出。
const source = [
{
entryID: 1,
entryName: "player1",
weight: 1900,
class:[],
},
{
entryID: 2,
entryName: "player1",
weight: 1900,
class:[],
},
{
entryID: 3,
entryName: "player2",
weight: 1900,
class:[],
},
{
entryID: 4,
entryName: "player3",
weight: 1900,
class:[],
},
{
entryID: 5,
entryName: "player4",
weight: 1900,
class:[],
},
{
entryID: 6,
entryName: "player5",
weight: 1900,
class:[],
},
{
entryID: 7,
entryName: "player6",
weight: 1900,
class:[],
},
{
entryID: 8,
entryName: "player7",
weight: 1900,
class:[],
},
{
entryID: 9,
entryName: "player8",
weight: 1900,
class:[],
},
{
entryID: 10,
entryName: "player9",
weight: 1900,
class:[],
},
{
entryID: 11,
entryName: "player10",
weight: 1900,
class:[],
},
{
entryID: 12,
entryName: "player11",
weight: 1900,
class:[],
},
{
entryID: 13,
entryName: "player12",
weight: 1900,
class:[],
},
{
entryID: 14,
entryName: "player1",
weight: 1900,
class:[],
},
];
console.log(combine(source))
function combine(data = [], different = 0, maxGroupSize = 2) {
const groups = [], related = [], sortedData = [...data].sort((a, b) => a.weight - b.weight),
alreadyInRela = (setX, eName) => {
let list = [...setX, eName]
return related.some(rela => list.every(l => rela.has(l)))
};
sortedData.forEach((el, indx) => {
let place = groups.findIndex( // find a place in a group forEach element, use indx as track
g => g.names.size < maxGroupSize // is the group incomplete ?
&& !g.names.has(el.entryName) // is entryName not in the group list (names Set) ?
&& (el.weight - g.weight) <= different
&& !alreadyInRela(g.names, el.entryName) // is (entryName + group list) does not already used ?
&& el.class.every(c => !g.usedClasses.has(c)) // check class
)
if (place < 0) { // not found -> create new group
let names = new Set().add(el.entryName) // create new group
groups.push({ names, indxs: [indx], weight: el.weight, usedClasses: new Set(el.class) }) // group constitutive info
related.push(names) // keep track of group list
} else { // find a place in a group
groups[place].names.add(el.entryName) // related list is also updated
el.class.forEach(c => groups[place].usedClasses.add(c)) // add classes
groups[place].indxs.push(indx) // add indx to retreive element in sortedData
}
});
return groups.reduce((r, g, i) => { // build result
if (g.indxs.length > 1) {
let key = `${i}_` + g.indxs.map(x => sortedData[x].weight).join('_')
r[key] = []
g.indxs.forEach(x => r[key].push(sortedData[x]))
}
return r
}, {})
}Run Code Online (Sandbox Code Playgroud)
当前结果:
{
0_1900_1900: [{ // 1st match
class: [],
entryID: 1,
entryName: "player1",
weight: 1900
}, {
class: [],
entryID: 3,
entryName: "player2",
weight: 1900
}],
1_1900_1900: [{ // 2nd match (As we can see here, player 1 has been matched again. There should be 3-6 matches before this player can be matched again)
class: [],
entryID: 2,
entryName: "player1",
weight: 1900
}, {
class: [],
entryID: 4,
entryName: "player3",
weight: 1900
}],
2_1900_1900: [{ // 3rd match
class: [],
entryID: 5,
entryName: "player4",
weight: 1900
}, {
class: [],
entryID: 6,
entryName: "player5",
weight: 1900
}],
3_1900_1900: [{ // 4th match
class: [],
entryID: 7,
entryName: "player6",
weight: 1900
}, {
class: [],
entryID: 8,
entryName: "player7",
weight: 1900
}],
4_1900_1900: [{ // 5th match
class: [],
entryID: 9,
entryName: "player8",
weight: 1900
}, {
class: [],
entryID: 10,
entryName: "player9",
weight: 1900
}],
5_1900_1900: [{ // 6th match
class: [],
entryID: 11,
entryName: "player10",
weight: 1900
}, {
class: [],
entryID: 12,
entryName: "player11",
weight: 1900
}],
6_1900_1900: [{ // 7th match
class: [],
entryID: 13,
entryName: "player12",
weight: 1900
}, {
class: [],
entryID: 14,
entryName: "player1",
weight: 1900
}]
}
Run Code Online (Sandbox Code Playgroud)
目标结果:
{
0_1900_1900: [{// 1st match
class: [],
entryID: 1,
entryName: "player1",
weight: 1900
}, {
class: [],
entryID: 3,
entryName: "player2",
weight: 1900
}],
1_1900_1900: [{ //2nd match
class: [],
entryID: 4,
entryName: "player3",
weight: 1900
}, {
class: [],
entryID: 5,
entryName: "player4",
weight: 1900
}],
2_1900_1900: [{ //3rd match
class: [],
entryID: 6,
entryName: "player5",
weight: 1900
}, {
class: [],
entryID: 7,
entryName: "player6",
weight: 1900
}],
3_1900_1900: [{ //4th match (As we can see here, there are 2 matches before player 1 got matched again. This is my target output)
class: [],
entryID: 2,
entryName: "player1",
weight: 1900
}, {
class: [],
entryID: 8,
entryName: "player7",
weight: 1900
}],
4_1900_1900: [{ //5th match
class: [],
entryID: 9,
entryName: "player8",
weight: 1900
}, {
class: [],
entryID: 10,
entryName: "player9",
weight: 1900
}],
5_1900_1900: [{ //6th match
class: [],
entryID: 11,
entryName: "player10",
weight: 1900
}, {
class: [],
entryID: 12,
entryName: "player11",
weight: 1900
}],
6_1900_1900: [{ //7th match
class: [],
entryID: 14,
entryName: "player1",
weight: 1900
}, {
class: [],
entryID: 13,
entryName: "player12",
weight: 1900
}]
}
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激。谢谢
此解决方案中将使用的所有变量:
currentPlayer--> 当前玩家,ashome或away。例如:{
"entryID": 1,
"entryName": "player1",
"weight": 1900,
"class": []
}
Run Code Online (Sandbox Code Playgroud)
match --> 表示特定比赛中的球员数组 ([ home, away])。例如:[
{
"entryID": 1,
"entryName": "player1",
"weight": 1900,
"class": []
},
{
"entryID": 3,
"entryName": "player2",
"weight": 1900,
"class": []
}
]
Run Code Online (Sandbox Code Playgroud)
data --> 给出了作为初始数据的玩家数组 ( source)。counter --> 每个 的计数器match。matchId --> counter_ home.weight_ away.weight。例如"0_1900_1900"matches --> 每个键都是 的所有匹配项matchId。例如:{
"0_1900_1900": [
{
"entryID": 1,
"entryName": "player1",
"weight": 1900,
"class": []
},
{
"entryID": 3,
"entryName": "player2",
"weight": 1900,
"class": []
}
],
"1_1900_1900": [
{
"entryID": 4,
"entryName": "player3",
"weight": 1900,
"class": []
},
{
"entryID": 5,
"entryName": "player4",
"weight": 1900,
"class": []
}
],
...
}
Run Code Online (Sandbox Code Playgroud)
分步解决方案:
datamatch数组中并从 中删除该玩家data。home.entryName等于away.entryName。
match数组中,并从数据中删除该玩家。home迭代中,则用 填充matchId,counter_home.weight否则用matchId连接_away.weight。matches键为matchId,值为match。希望它会有所帮助。
const source = [
{
entryID: 1,
entryName: "player1",
weight: 1900,
class:[],
},
{
entryID: 2,
entryName: "player1",
weight: 1900,
class:[],
},
{
entryID: 3,
entryName: "player2",
weight: 1900,
class:[],
},
{
entryID: 4,
entryName: "player3",
weight: 1900,
class:[],
},
{
entryID: 5,
entryName: "player4",
weight: 1900,
class:[],
},
{
entryID: 6,
entryName: "player5",
weight: 1900,
class:[],
},
{
entryID: 7,
entryName: "player6",
weight: 1900,
class:[],
},
{
entryID: 8,
entryName: "player7",
weight: 1900,
class:[],
},
{
entryID: 9,
entryName: "player8",
weight: 1900,
class:[],
},
{
entryID: 10,
entryName: "player9",
weight: 1900,
class:[],
},
{
entryID: 11,
entryName: "player10",
weight: 1900,
class:[],
},
{
entryID: 12,
entryName: "player11",
weight: 1900,
class:[],
},
{
entryID: 13,
entryName: "player12",
weight: 1900,
class:[],
},
{
entryID: 14,
entryName: "player1",
weight: 1900,
class:[],
},
];
console.log(combine(source));
function combine(data) {
let matches = {};
let match = [];
let matchId = '';
let matchCounter = 0;
let home, away;
let currentPlayer;
while(data.length) { // Step 1
currentPlayer = data[0];
if(match.length) { // Step 2
away = currentPlayer;
if(home.entryName !== away.entryName) {
match.push(currentPlayer);
data.shift();
matchId += `_${currentPlayer.weight}`;
matches[matchId] = match; // Step 4
match = []; matchId = ''; matchCounter++;
} else {
arraymove(data, 0, 5);
}
} else {
match.push(currentPlayer);
home = currentPlayer;
data.shift();
matchId = `${matchCounter}_${currentPlayer.weight}`; // Step 3
}
}
return matches;
}
function arraymove(arr, fromIndex, toIndex) {
let element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}Run Code Online (Sandbox Code Playgroud)