I am trying to generate a dictionary automatically with a for loop (i < numero_usuarios), the keys are taken from a list with names, and the values are randomly generated with a random.randint(1, 10), the problem is that it does not always generate the amount I want.
For instance, I want to create 10 users(usuarios), it sometimes creates 7, 8 or 9, but rarely 10.
Code below.
import random
class practica6:
#Create our constructor
def __init__(self) -> None:
# Initialize users dictionary
self.usuarios = {}
#List of possible names the users can take
self.nombres = ['Mario', 'Pepe', 'Angel', 'Joaquin', 'Jesus', 'Edson', 'Emilio',
'Eli', 'Francisco', 'Sergio',
'Erick', 'David', 'Liam', 'Noah', 'Oliver', 'William', 'James', 'Benjamin', 'Lucas',
'Henry', 'Alexander',
'Mason', 'Michael', 'Ethan', 'Mateo', 'Sebastian', 'Jack', 'Peter', 'Josh',
'Patricia', 'Luis', 'Gerardo', 'Carmen']
def generar_diccionario_usuarios(self, numero_usuarios : int):
#Generate a dictionary with random names (keys) and random priority (values) keys :
#values
for i in range(numero_usuarios):
self.usuarios[random.choice(self.nombres)] = random.randint(1, 10)
#DEBUG : Print our users dictionary
print(self.usuarios)
#Test app
practica = practica6()
n = 10
print('Usuarios:')
practica.generar_diccionario_usuarios(n)
CodePudding user response:
In a dictionary, a key cannot appear multiple times, and all attempts to insert a key which exists already will result in overwriting the stored value.
random.choice
, being a draw with replacement, can return the same user multiple times. You need to use random.sample
, which simulates a draw without replacement:
for nombre in random.sample(self.nombres, numero_usuarios):
self.usuarios[nombre] = random.randint(1, 10)
CodePudding user response:
the problem is that sometimes the "random.choice(self.nombres)" generates the same name so it overights, so the solution is :
import random
class practica6:
#Create our constructor
def __init__(self) -> None:
# Initialize users dictionary
self.usuarios = {}
#List of possible names the users can take
self.nombres = ['Mario', 'Pepe', 'Angel', 'Joaquin', 'Jesus', 'Edson', 'Emilio',
'Eli', 'Francisco', 'Sergio',
'Erick', 'David', 'Liam', 'Noah', 'Oliver', 'William', 'James', 'Benjamin', 'Lucas',
'Henry', 'Alexander',
'Mason', 'Michael', 'Ethan', 'Mateo', 'Sebastian', 'Jack', 'Peter', 'Josh',
'Patricia', 'Luis', 'Gerardo', 'Carmen']
def generar_diccionario_usuarios(self, numero_usuarios : int):
#Generate a dictionary with random names (keys) and random priority (values) keys :
#values
for i in range(numero_usuarios):
name = random.choice(self.nombres)
while name in self.usuarios.keys():
name = random.choice(self.nombres)
self.usuarios[name] = random.randint(1, 10)
#DEBUG : Print our users dictionary
print(self.usuarios)
#Test app
practica = practica6()
n = 10
print('Usuarios:')
practica.generar_diccionario_usuarios(n)
thank you, hope it wokrs cuz it worked for me!
CodePudding user response:
It's because you get duplicate keys in your dict when choosing one randomly at a time.
You could generate a list of numero_usarios
distinct keys with
distinct_names = random.sample(self.nombres, k=numero_usarios)
and a list of random integers with
values = random.choices(range(1, 11), k=numero_usarios)
Then you can build the dict by pairing these lists with
self.usuarios = dict(zip(distinct_names, values))
CodePudding user response:
I think the problem is that sometimes, when picking a random name- that name could already be in the dict. Why not randomise the names from the start, and as they are added to the dict, remove them from the list?
import random
class Practica6:
def __init__(self) -> object:
# Initialize users dictionary
self.usuarios = {}
#List of possible names the users can take- shuffled
self.nombres = random.shuffle(['Mario', 'Pepe', 'Angel', 'Joaquin', 'Jesus', 'Edson', 'Emilio',
'Eli', 'Francisco', 'Sergio',
'Erick', 'David', 'Liam', 'Noah', 'Oliver', 'William', 'James', 'Benjamin', 'Lucas',
'Henry', 'Alexander',
'Mason', 'Michael', 'Ethan', 'Mateo', 'Sebastian', 'Jack', 'Peter', 'Josh',
'Patricia', 'Luis', 'Gerardo', 'Carmen'])
def generar_diccionario_usuarios(self, numero_usuarios : int):
#Generate a dictionary with random names (keys) and random priority (values) keys :
#values
for i in range(numero_usuarios):
chosen = self.nombres.pop() # random.choice(self.nombres)
self.usuarios[chosen] = random.randint(1, 10)
#DEBUG : Print our users dictionary
print(self.usuarios)
#Test app
practica = Practica6()
n = 5
print('Usuarios:')
practica.generar_diccionario_usuarios(n)
The init always returns an instance of the class. I think this code above may achieve what you are looking for? Alternatively it might be good to make a "factory" function to generate many instances of an object with varying properties, rather than have it as a method. Just a thought.