javascript - 为每个用户随机分配至少一个唯一项,不重复
问题描述
为每个用户随机分配至少一个唯一项目。例如,如果 5 个项目和 5 个用户,每个用户获得 1 个项目。如果 4 个项目和 5 个用户,则只有 4 个用户每人获得 1 个项目。如果 7 个项目和 4 个用户,则 3 个用户每人得到 2 个项目,1 个用户得到 1 个项目,依此类推。下面的脚本旨在实现这一目标,但得到了错误的结果。
assignItemsToUsers() {
let items = [
{
id: 1,
name: "item1",
tag: 1900
},
{
id: 2,
name: "item2",
tag: 1876
},
{
id: 3,
name: "item3",
tag: 1575
},
{
id: 4,
name: "item4",
tag: 4783
},
{
id: 5,
name: "item5",
tag: 67894
},
{
id: 6,
name: "item6",
tag: 66789
},
{
id: 7,
name: "item7",
tag: 67890
},
{
id: 8,
name: "item8",
tag: 87654
},
{
id: 9,
name: "item9",
tag: 94948
}
];
let users = [
{
id: 1,
name: "user1",
userID: 38494
},
{
id: 2,
name: "user2",
userID: 84844
},
{
id: 3,
name: "user3",
userID: 47483
},
{
id: 4,
name: "user4",
userID: 83735
}
];
let results = [];
let tempResults = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
const randomUser = users[Math.floor(Math.random() * users.length)];//pick user at random
randomUser.tempitem = item;//asign item to this user
tempResults.push(randomUser);//push to tempResults
}
//Group assigned items to their respective user
for (let i = 0; i < users.length; i++) {
const user = users[i];
let myluckyitems = [];
for (let index = 0; index < tempResults.length; index++) {
//check where tempResults[index].id == user.id
const assigneduser = tempResults[index];
if (user.id == assigneduser.id) {
//True: this was the assigned user.
myluckyitems.push(assigneduser.tempitem);
}
}
//all items assigned, then append to user object & push to results
if (myluckyitems.length > 0) {
user.items = myluckyitems;
results.push(user);
}
}
console.log(results);
}
实际结果
results = [
{
id: 1,
name: user1,
userID: 38494,
items: [
{
id: 1,
name: item1,
tag: 1900
},
{
id: 1,
name: item1,
tag: 1900
}
],
tempitem: {
id: 1,
name: item1,
tag: 1900
},
},
{
id: 2,
name: user2,
userID: 84844,
items: [
{
id: 2,
name: item2,
tag: 1876
},
{
id: 2,
name: item2,
tag: 1876
},
{
id: 2,
name: item2,
tag: 1876
},
],
tempitem: {
id: 2,
name: item2,
tag: 1876
},
},
{
id: 3,
name: user3,
userID: 47483,
items: [
{
id: 3,
name: item3,
tag: 1575
},
{
id: 3,
name: item3,
tag: 1575
}
],
tempitem: {
id: 3,
name: item3,
tag: 1575
},
},
{
id: 4,
name: user4,
userID: 83735,
items: [
{
id: 4,
name: item4,
tag: 4783
},
{
id: 4,
name: item4,
tag: 4783
}
],
tempitem: {
id: 4,
name: item4,
tag: 4783
},
}
];
预期成绩
results = [
{
id: 1,
name: user1,
userID: 38494,
items: [
{
id: 1,
name: item1,
tag: 1900
},
{
id: 5,
name: item5,
tag: 67894
},
{
id: 9,
name: item9,
tag: 94948
}
],
},
{
id: 2,
name: user2,
userID: 84844,
items: [
{
id: 2,
name: item2,
tag: 1876
},
{
id: 6,
name: item6,
tag: 66789
},
],
},
{
id: 3,
name: user3,
userID: 47483,
items: [
{
id: 3,
name: item3,
tag: 1575
},
{
id: 7,
name: item7,
tag: 67890
},
],
},
{
id: 4,
name: user4,
userID: 83735,
items: [
{
id: 4,
name: item4,
tag: 4783
},
{
id: 8,
name: item8,
tag: 87654
},
],
}
];
不同之处在于,实际结果为每个用户返回重复的项目,并不是所有项目都分配给用户,它还将tempitem
属性附加到每个用户,这是不需要的。
预期结果,将唯一的项目分配给每个用户而不重复,并确保必须将项目分配给用户。
解决方案
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function assign() {
const itemsLength = items.length;
for (var i=itemsLength+1, shuffledArray=[]; i--;) shuffledArray.push(i);
shuffledArray = shuffleArray(shuffledArray);
const eachUserItems = itemsLength/users.length;
Object.entries(users).map(([key, value]) => {
for(i = 0; i < Math.round(eachUserItems); i++) {
users[key]['items'] = users[key]['items'] || [];
var popNewIndex = shuffledArray.pop();
var objectToInsert = items.find((i) => i.id == popNewIndex + 1);
users[key]['items'].push(objectToInsert);
}
});
return users;
}
这将为您提供始终随机分配给用户的预期项目
附言。
这里还有一个简单的想法是,我们不会在每个循环上随机化,而是制作一个随机值列表,我们将一个一个地弹出。我们可以使用随机值通过 id 从列表中获取值并分配它。由于列表应该具有随机的唯一值,因此它可以确保没有值再次分配给任何其他用户。
推荐阅读
- laravel - 调用未定义的方法 App\Models\StudentModel::createToken()
- reactjs - Firebase 部署到自定义子域(不是项目 ID)
- javascript - LexicalEnvironment 和 VariableEnvironment 是如何工作的?
- java - 加载配置文件时,是否可以默认不包含返回的 Config 实例中的 Java 属性?
- python - Discord Py / 如何从服务器用户中删除特定角色
- django - 序列化程序中的 django-rest-framework 访问字段
- php - Laravel 访问 web.php 中的会话数据
- haskell - 如何将列表中第一个元素的所有出现移动到Haskell中列表的末尾?
- java - Split() Java 中带有换行符的表达式
- c - 我可以从 STDOUT_FILENO 中读取()吗?