Python evenly distribute value to a list in a dictionary

4119 views python
10

I have the following code which assigns numbers at random to employees:

emp_numbers = {}
employees = ['empA', 'empB', 'empC', 'empD', 'empE', 'empF']
numbers = 26
for x in employees:
    emp_numbers[x] = []
emp = list(emp_numbers.keys())

for number in range(1, numbers+1):
    emp_name = choice(emp);
    emp_numbers[emp_name].append(number)
print (emp_numbers)

Output:

{'empA': [4, 25], 'empB': [2, 10, 11, 15, 18, 20, 22, 23], 'empC': [5, 13, 21, 24], 'empD': [3, 6, 7, 8, 12, 16, 19, 26], 'empE': [14], 'EmpF': [1, 9, 17]}

It works great. However, I don't know how to get it to distribute the numbers as evenly as possible. Some employees are getting 2 numbers, some have 8. Any advice on how to get it do that?

Thanks!

answered question

2 Answers

10

Assuming the count of numbers is evenly divisible with the number of employees, you could go about it this way:

import random
import collections


employees = ["empA", "empB", "empC", "empD", "empE", "empF"]  # employee names
numbers = list(range(1, 27))  # numbers from 1..26

emp_numbers = collections.defaultdict(list)  # collects the employee numbers
random.shuffle(numbers)  # shuffle the numbers to distribute

for i, number in enumerate(numbers):  # get the index of the number and the number
    employee = employees[i % len(employees)]  # round-robin over the employees...
    emp_numbers[employee].append(number)  # ... and associate a number with a name.

print(emp_numbers)

outputs e.g.

{'empF': [25, 4, 9, 21], 'empD': [2, 10, 3, 11], 'empE': [18, 5, 17, 15], 'empB': [7, 24, 26, 6, 8], 'empC': [1, 14, 13, 12], 'empA': [16, 23, 20, 19, 22]}

If the numbers aren't evenly divisible, some folks will get more numbers than others.

posted this
9

Since you want to assign all numbers, you can randomise the order of numbers instead of employees:

numbers = list(range(1, 27))
random.shuffle(numbers)

You can then use slicing to get an even count of numbers for every employee:

for idx, employee in enumerate(employees):
    emp_numbers[employee] = numbers[idx::len(employees)]

The [start::n] syntax selects every n'th item beginning at start. The first employee gets item 0, 6, 12, ..., the second gets item 1, 7, 13, ..., and so on.

posted this

Have an answer?

JD

Please login first before posting an answer.