Как избежать ошибки "RuntimeError: измененный размер слова во время итерации"?

Я проверил все другие вопросы с той же ошибкой, но не нашел полезного решения =/

У меня есть словарь списков:

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

в котором некоторые из значений пустые. В конце создания этих списков я хочу удалить эти пустые списки перед возвратом моего словаря. Текущий я пытаюсь сделать это следующим образом:

for i in d:
    if not d[i]:
        d.pop(i)

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

Ответ 1

В Python 2.x вызов keys делает копию ключа, который вы можете перебирать при изменении dict:

for i in d.keys():

Обратите внимание, что это не работает в Python 3.x, потому что keys возвращает итератор вместо списка.

Другим способом является использование list для принудительного копирования ключей. Это также работает в Python 3.x:

for i in list(d):

Ответ 2

Просто используйте словарь, чтобы скопировать соответствующие элементы в новый dict

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}

Ответ 3

Вам нужно всего лишь использовать "копию":

Таким образом, вы перебираете исходные словарные поля и на лету можете изменить нужный dict (d dict). Он работает над каждой версией python, поэтому он более понятен.

In [1]: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

In [2]: for i in d.copy():
   ...:     if not d[i]:
   ...:         d.pop(i)
   ...:         

In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}

Ответ 4

Я попытался бы избежать вставки пустых списков в первую очередь, но, как правило, использовал бы:

d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty

Если до 2.7:

d = dict( (k, v) for k,v in d.iteritems() if v )

или просто:

empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
    del[k]

Ответ 5

Для Python 3:

{k:v for k,v in d.items() if v}

Ответ 6

В подобных ситуациях я хотел бы сделать глубокую копию и пройтись по ней, изменяя исходный текст.

Если поле поиска находится в списке, вы можете перечислить его в цикле for списка, а затем указать позицию в качестве индекса для доступа к полю в исходном dict.

Ответ 7

Причина ошибки во время выполнения состоит в том, что вы не можете выполнять итерацию по структуре данных, пока ее структура изменяется во время итерации.

Одним из способов достижения того, что вы ищете, является использование списка для добавления ключей, которые вы хотите удалить, а затем использование функции pop в словаре для удаления идентифицированного ключа во время итерации по списку.

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
pop_list = []

for i in d:
        if not d[i]:
                pop_list.append(i)

for x in pop_list:
        d.pop(x)
print (d)

Ответ 8

Вы не можете выполнять итерацию по словарю во время его изменения во время цикла for. Сделайте приведение в список и переберите этот список, он мне подходит.

    for key in list(d):
        if not d[key]: 
            d.pop(key)