Назначает по крайней мере один уникальный элемент каждому пользователю в случайном порядке без повторения - PullRequest
0 голосов
/ 03 августа 2020

Назначьте как минимум один уникальный предмет каждому пользователю наугад. например, если 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 к каждому пользователю, которое не требуется.

Ожидаемые результаты, назначает уникальные элементы каждому пользователю без повторения, а также гарантирует, что элемент должен быть назначен пользователю.

Ответы [ 4 ]

1 голос
/ 03 августа 2020
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;
}

Это даст вам ожидаемые элементы, всегда назначаемые случайным образом пользователям

ps.

Также простая идея состоит в том, что вместо того, чтобы выполнять случайный выбор для каждого l oop, мы бы сделали случайный список значений, которые мы будем выдавать одно за другим. Мы можем использовать случайное значение, чтобы извлечь значение из списка по идентификатору и присвоить его. Поскольку список должен иметь уникальные значения, которые рандомизированы, он гарантирует, что никакое значение не будет снова присвоено любому другому пользователю.

0 голосов
/ 03 августа 2020

Попробуем упростить вашу задачу, представим, что у вас неизвестное количество элементов

const items = [1, 5, 6, 7, 3, 4, 2, 3, 2];

и неизвестное количество пользователей

const users = [{ name: "Tom", items: []}, { name: "John", items: [] }, name: "Steve", items: [] }];

, и вы должны назначить эти элементы пользователю, чтобы ваш код был

const items = [1, 5, 6, 7, 3, 4, 2, 3, 2];
const users = [{ name: "Tom", items: []}, { name: "John", items: [] }, { name: "Steve", items: [] }];
let currentUserIndex = 0;

while (items.length) {
   const randomIndex = Math.floor(Math.random() * items.length);
    
   users[currentUserIndex].items.push(items[randomIndex]);
   
   items.splice(randomIndex, 1);
   
   if (currentUserIndex === users.length - 1) {
    currentUserIndex = 0;
   } else {
    currentUserIndex++; 
   }
}
0 голосов
/ 03 августа 2020

Проверьте следующий код. Он протестирован и дает ожидаемый результат.

const minItems = Math.round(items.length / users.length);
const assignedItems = [];

const usersWithItems = users.map((user) => {
   user.items = new Array(minItems).fill(0).map(() => {
      let isNew = false;
      let item;
      do {
          item = items[Math.floor(Math.random() * items.length)];
          if(!assignedItems.includes(item.id))
            isNew = true;
      } while(isNew == false);
      if(item){
          assignedItems.push(item.id);
          return item;
      }
   });
   return user; 
})

const balanceItems = items.filter(item => !assignedItems.includes(item.id));
balanceItems.forEach((item) => {
  const randomUserNo = Math.floor(Math.random() * users.length);
  usersWithItems[randomUserNo].items.push(item);
})

console.log(usersWithItems);
0 голосов
/ 03 августа 2020

Можно сделать что-то подобное (извините за возможные ошибки, не тестировал)

const users = [...] 
const items = [...]
const results = []

const random_func = () => {
   let available_users = [...users]
   items.forEach(item => {
        
       // if available users are zero, re-populate the array (it means that everyone has a item
        if(available_users.length === 0) available_users = [...users]
       //get a random user from available users array
       const random_user_index = Math.floor(Math.random() * available_users.length)
       const temp_user = available_users(random_user_index)

       //remove user from available users
       available_users.splice(i, 1);
       
       //check if user already exists into results array
       if(results.length > 0) {
          objIndex = results.findIndex((obj => obj.id == temp_user.id));
          if(objIndex === -1) results.push({...temp_user, items: [{...item}]}
          else results[index].items.push(item)
        }else {
           results.push({...temp_user, items: [{...item}]}
        }
   })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...