提问人:Phil-Absynth 提问时间:11/3/2023 最后编辑:jonrsharpePhil-Absynth 更新时间:11/4/2023 访问量:63
如何多次平均获取数组的随机元素?
How to get random elements of an array multiple times equally?
问:
我有一个月的表,表的每一天都有一行,还有一个带有名称的数组。对于每一天,都应该从数组中随机选择一个名称,而如果可能的话,每个名称都应该选择大约相同的次数。
以下函数检查数组中的每个用户在某一天是否可用,如果没有,则排除名称。
function generateRandomSchedule(month) {
// some more code including variable declaration here
for(let i=1; i<daysInMonth+1; i++) {
let date = `${moment(i, 'D').format('DD')}.${monthNumber}.`;
// filter required keys
const keys = Object.keys(localStorage).filter(key => key.includes(date) && !key.startsWith(month));
let excludeUsers = [];
keys.forEach((key) => {
let keyValue = localStorage.getItem(key);
// check if user is available for the certain day
if(key.includes('Urlaub') && dutyUserArray.includes(keyValue)) {
excludeUsers.push(keyValue);
}
if(key.includes('Spaet') && dutyUserArray.includes(keyValue)) {
excludeUsers.push(keyValue);
}
})
// remove unavailable users from array
let updatedArray = dutyUserArray.filter(user => !excludeUsers.includes(user));
// get random user from the available users
let randomName = updatedArray[Math.floor(Math.random() * updatedArray.length)];
// some more code to add randomName to table here
}
}
到目前为止,这段代码工作正常,只是它不均匀地选择随机数组元素,例如 name1 已添加到表中 6 次,而 name2 仅添加一次,name3 添加 4 次。
答:
0赞
phatfingers
11/4/2023
#1
我将首先确定具有最小可用天数的用户,以及池中的用户数。如果 ,则将每个用户的时间复制到列表中,然后添加“虚拟”用户以使列表与当月的天数匹配,否则均匀复制循环样式,直到匹配天数。在两个被欺骗用户列表之间执行“稳定婚姻”匹配(参见 Gale-Shapley 算法),直到天。minDays*poolSize <= monthSize
minDays
monthSize - minDays*poolSize
创建一个新列表,其中所有用户省略了与先前的最小可行天数匹配的用户,并针对任何不匹配或虚拟匹配的天数对该组用户重复上述过程。
继续这样做,直到所有日期都匹配。在这一点上,时间表可能无法解决。简单来说,您可以有一个包含 1 个用户的池,在一个月的 30 天内有 1 天可用。
解决后,迭代匹配的用户日,在允许的情况下在用户日之间执行随机交换。dutyUserArray
评论
updatedArray