Home > Back-end >  giving random array to dictionary in a list
giving random array to dictionary in a list

Time:03-23

Im having some problems with structuring my for loops. I want the numbers generated by random.randint to be different for each settings list in every dictionary.

PopulationSize = 2
AmountofSettings = 5
key_index = '_index'
key_par = 'Fitness'
key_set = 'Settings'
data_set = [0] * PopulationSize
dict_per = {}
settings_per = [0] * AmountofSettings

These give the variables and names of the keys in every dictionary

for i in range(len(data_set)):

in this for-loop I am going through every dictionary in the list.

    for x in range(len(settings_per)):
        settings_per[x] = random.randint(0, 9)

I believe my problem is in this part. currently it constructs a list of 5 random integers, and assigns it to the 'Settings' key in every dictionary. My goal is to have a new list in 'Settings' in each dictionary.

        dict_per = {key_index: i, key_par: None, key_set: settings_per}
    data_set[i] = dict_per 
print(data_set)

The data structure coming out is correct. However, every 'Settings' list in the main dictionary list contains the same integers. I want the lists to be all different.

For extra clarity. This is the output right now for the data_list. As you can see, the 'Settings' are the same list of variables. I want the 'Settings' lists to be different for every dict.

Output right now:

[{'_index': 0, 'Fitness': None, 'Settings': [1, 7, 5, 4, 8]}, {'_index': 1, 'Fitness': None, 'Settings': [1, 7, 5, 4, 8]}]

But the output that I want:

[{'_index': 0, 'Fitness': None, 'Settings': [1, 7, 5, 4, 8]}, {'_index': 1, 'Fitness': None, 'Settings': [4, 6, 8, 1, 3]}]

where the second 'Settings' list is independent of the first.

CodePudding user response:

Your problem is that you allocate Settings_per once, then set the same reference for each new dict_per that you make: key_set: Settings_per.

You might think that dict_per has the same issue, but it does not. Notice that in each iteration, you assign a new dictionary object to that name (dict_per = {...}), despite the fact that you initialize it to an empty dictionary in the beginning.

Start by removing the unnecessary allocations at the beginning: dict_per and Settings_per. Create settings_per properly in each iteration, as you do with dict_per, rather than just filling it in.

Next, notice that dict_per is being generated over and over, for each element of settings_per. There is no need to do that. You only need to generate it once.

It is conventional to use snake_case for most variable and fuction names in python. CamelCase is generally used with user-defined class names. Constants are conventionally written as UPPERCASE_WITH_UNDERSCORES.

Here is what the code looks like with these changes:

POPULATION_SIZE = 2
SETTINGS_COUNT = 5
KEY_INDEX = '_index'
KEY_PAR = 'Fitness'
KEY_SET = 'Settings'
data_set = [None] * POPULATION_SIZE

for i in range(POPULATION_SIZE):
    settings_per = [None] * SETTINGS_COUNT
    for x in range(SETTINGS_COUNT):
        settings_per[x] = random.randint(0, 9)
    dict_per = {KEY_INDEX: i, KEY_PAR: None, KEY_SET: settings_per}
    data_set[i] = dict_per
print(data_set)

The code above is already totally functional, but you can make it better. First satisfy yourself that you can rewrite the inner loop as follows:

settings_per = []
for x in range(SETTINGS_COUNT):
    settings_per.append(random.randint(0, 9))

That's the idiomatic expanded equivalent for a list comprehension:

settings_per = [random.randint(0, 9) for _ in range(SETTINGS_COUNT)]

_ is often used to indicate a discarded loop variable.

Now you can write the entire outer loop as

data_set = [None] * POPULATION_SIZE
for i in range(POPULATION_SIZE):
    data_set[i] = {KEY_INDEX: i, KEY_PAR: None, KEY_SET: [random.randint(0, 9) for _ in range(SETTINGS_COUNT)]}

Now the outer loop is beginning to loop just like the form of the inner loop that we converted to a list comprehension. And indeed, there is a dictionary comprehension syntax available as well:

data_set = {KEY_INDEX: i, KEY_PAR: None, KEY_SET: [random.randint(0, 9) for _ in range(SETTINGS_COUNT)] for i in range(POPULATION_SIZE)}

CodePudding user response:

Your mistake is at

for x in range(len(Settings_per)):
        Settings_per[x] = random.randint(0,9) #replace for better initialization
        dict_per= {key_index: i, key_par: None, key_set: Settings_per} # Here

which could be fixed by:

for i in range(len(data_set)):
    for x in range(len(Settings_per)):
        Settings_per[x] = random.randint(0,9)
    dict_per= {key_index: i, key_par: None, key_set: Settings_per}
    data_set[i] = dict_per 
  • Related