Каков правильный способ удаления элемента из словаря в цикле «for» (Python)?

#python

#python

Вопрос:

Я хочу выполнить итерацию словаря, проверить значение и удалить элементы, соответствующие определенным значениям.

Пример

 d = {1, 1, 2, 1, 4, 5}   
for i in d:
  if i == 1:
    del i
  

Но мы знаем, что делать это опасно, поскольку список обновляется во время итерации. Какой чистый способ сделать это в Python?

Комментарии:

1. Я полагаю, вы имеете в виду d = [1,1,2,1,4,5] (т. Е. скобки, а не фигурные скобки)?

2. почему это получает отрицательный результат. Я новичок в Python и хотел бы знать, как это сделать?

3. Потому что в вашем вопросе задается вопрос о dictionary, но ваш код не имеет допустимого синтаксиса для dictionary и описывает операцию, которая является бессмысленной для словаря.

4. Даже игнорируя эту проблему, ваш пример ничего не делает, кроме перебора коллекций и (бессмысленно) удаления переменной итерации. Вам следует пересмотреть свое понимание переменных и del . Тем не менее, вопрос актуален.

Ответ №1:

Если k — это ваш словарь, вы можете сделать

 k = {x:v for x,v in k.iteritems() if x != 1}
  

Для 2.7 и 3.0

Для чего-либо более старого вы можете сделать

 k = dict((x,v) for x,v in k.iteritems() if x!=1)
  

Комментарии:

1. Примечание: Поддерживается только в Python 3.X и 2.7 .

2. Спасибо. Я обновил его, чтобы включить что-то для более старых версий Python.

Ответ №2:

Я бы рекомендовал вам использовать встроенную filter функцию, поскольку так более понятно, что будет сделано со списком. Также filter работает с любым итерируемым: последовательностью, контейнером или итератором.

Вот пример того, как работать с функцией

 In [2]: d = [1,1,2,1,4,5]

In [3]: filter(lambda x: (x!=1), d)
Out[3]: [2, 4, 5]
  

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

Документация по filter доступна по адресу http://docs.python.org/library/functions.html#filter

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

Комментарии:

1. filter не очень по-питоновски. Вместо этого было бы лучше использовать понимание списка.

2. @NoufalIbrahim Я мог бы написать что-то подобное [el for el in d if el != 1] , но это будет работать только со списками, а не с кортежами, например. Также обратите внимание, что фрагмент кода с filter функцией поймет больше программистов, и будет проще перенести программу, например, на другой язык.

3. Почему это не будет работать для кортежей? Это также поддерживает протокол iterator. Ваш второй пункт на самом деле неверен. Фильтр с помощью лямбда-выражения в Python работает намного медленнее, а преимуществ переносимости и удобочитаемости недостаточно, чтобы компенсировать плохой стиль.

4. @NoufalIbrahim Дай мне посмотреть. Если я буду использовать filter подход, он будет работать следующим образом: codepad.org/gLKtSBT7 Мне не нужно ничего менять, чтобы фильтровать кортежи (и filter вернет кортеж вместо списка). Как я могу достичь этого, используя понимание списка? Я попробовал и получил это codepad.org/yi327lgN , поэтому для фильтрации кортежа мне нужно изменить код фильтрации (использовать что-то вроде tuple([x for x in d if x!=1]) )

5. @NoufalIbrahim также меня не волнует, насколько медленными являются лямбды в Python, пока вся программа не будет работать хорошо. И даже в случае некоторых проблем с производительностью я сначала использую profiler вместо того, чтобы пытаться реализовать некоторые преждевременные оптимизации.

Ответ №3:

 for j in range(len(d)-1,-1,-1):
  if d[j] == 1:
    del d[j]
  

Комментарии:

1. Это работает для списков, но является уродливым, неочевидным, не распространяется на непоследовательности (словари, наборы и т.д.) И Редко требуется.

2. Согласен. for i in range(len(something)) это почти всегда плохой знак.

Ответ №4:

Хотя обычно я бы просто создал новый словарь (см. Ответ Нуфаля Ибрагима), вы можете безопасно модифицировать существующий словарь на месте, получив список ключей и выполнив итерацию по нему:

 for k in d.keys():
    if d[k] == 1:
        del d[k]
  

Комментарии:

1. Примечание: Работает в Python 2.X, но в 3.X d.keys() возвращает представление словаря и завершается с ошибкой RuntimeError: dictionary changed size during iteration . Используйте list(d.keys()) в 3.X.