Search code examples
pythonpython-2.xpython-itertools

Can someone please explain this error - "Runtime error: dictionary size changed during iteration"?


def find_the_best_solution(shipping_request, list, current_solution, best_shipping_solution):
    if shipping_request == {}:
        return current_solution

    for item in shipping_request:
        for i in range(0,len(list), 1):
            length_of_combination = i+1
            combinations = itertools.combinations(list, length_of_combination)
            for x in combinations:
                if sum(x) >= shipping_request[item]:
                    if sum(x) > shipping_request[item]:
                        current_solution['wastage'] += (sum(x) - shipping_request[item])
                    current_solution['number_of_containers'] += length_of_combination
                    current_solution['distribution'][item] = x
                    temp_request = shipping_request
                    del temp_request[item]
                    temp_list = list
                    for y in x:
                        temp_list.remove(y)
                    solution = find_the_best_solution(temp_request, temp_list, current_solution, best_shipping_solution)
                    if solution['wastage'] < best_shipping_solution['wastage']:
                        best_shipping_solution = solution
                    elif solution['wastage'] == best_shipping_solution['wastage']:
                        if solution['number_of_containers'] < best_shipping_solution['number_of_containers']:
                            best_shipping_solution = solution

    return best_shipping_solution   

This gives the following error- "Runtime error: dictionary size changed during iteration"

What am I doing wrong? How can I do it differently?


Solution

  • This has nothing to do with itertools.combinations, you are trying to change the structure of data you are iterating over, which is not allowed:

    Runtime error: dictionary size changed during iteration
    

    You are trying to add or delete keys from a dictionary as you iterate it. A workaround is to iterate over for key in list(dictionary) which makes a copy list of the dictionary's keys, so you can still modify the underlying dictionary, however you may also want to reconsider your general approach.

    The lines causing the error are:

    for item in shipping_request:
    
        for i in range(0,len(list), 1):
                ...
                for x in combinations:
                    if sum(x) >= shipping_request[item]:
                        if sum(x) > shipping_request[item]:
                            ...
                        temp_request = shipping_request
                        del temp_request[item] # you are trying to delete a key from 
                                               # shipping_request as you iterate it
    

    Perhaps you want to make a shallow copy eg. temp_request = dict(shipping_request) which makes a new dictionary with references to the same objects. However you may want a import copy; copy.deepcopy to recursively copy every object inside the dictionary.