2016-12-06 2 views
0

Я хочу, чтобы удалить некоторые элементы в словаре в цикле, то я следую коды из этого How to delete items from a dictionary while iterating over it?Как удалить элементы в словаре в цикле

Looping над .keys:

b = {'a':1, 'b' : 2} 
for k in b.keys(): 
    if b[k] == 1: 
     del b[k] 

Результаты в:

Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 
b 
{'b': 2} 

Итерирование над .items():

b = {'a':1, 'b' : 2} 
for k, v in b.items(): 
    if v == 1: 
     del b[k] 

Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 
b 
{'b': 2} 

После этого цикла возвращается правильный результат, но RuntimeError также поднят, как я могу его исправить?

ответ

3

Вы изменить d с del d[k] так итерация это .keys или .values нет никакой разницы, вы изменяете основной итератор и поэтому он жалуется.

Вы можете либо сделать list из .keys с list(b) или .items с list(b.items()), по существу, копируя их в новый итератора, который не относится к словарю вы изменения:

# list(b) would suffice instead of .keys 
for k in list(b.keys()): 
    if b[k] == 1: 
     del b[k] 

или, используя соображения диктата:

d = {k:b[k] for k in b if b[k] != 1} 

для отфильтровывания нежелательных элементов.

+0

'list' тоже не нужно. для k в v будет работать одинаково. – user312016

+0

В чем 'v' вы имеете в виду? @ user312016 –

+0

О, я пропустил ваш вопрос, мой пример был плохим, b вместо v: для k в b. – user312016

2

Вы не можете удалить элементы в dict, итерации по нему.

Лучше всего было бы использовать dict понимание:

b = {'a':1, 'b' : 2} 
b = {k: v for k, v in b.items() if v != 1} 

Вы также можете сделать копию dict в то время как итерация над ним:

b = {'a':1, 'b' : 2} 
for k, v in dict(b).items(): 
    if v == 1: 
     del b[k] 

Здесь, вы Перебор копия b при изменении оригинала b, поэтому он работает: вы никогда не удаляете элементы из копии.

Смежные вопросы