키를 알 수없는 경우 사전에서 항목 제거


112

값을 기준으로 사전에서 항목을 제거하는 가장 좋은 방법은 무엇입니까 (예 : 항목의 키를 알 수없는 경우)? 다음은 간단한 접근 방식입니다.

for key, item in some_dict.items():
    if item is item_to_remove:
        del some_dict[key]

더 좋은 방법이 있습니까? 반복하는 동안 사전에서 변경 (항목 삭제)하는 데 문제가 있습니까?


1
dict를 반복하는 동안 mutating dict를 금지하는 밑줄 이유는 내부적으로 반복 순서가 있기 때문입니다. 키를 변경하면 순서가 손상되어 알 수없는 동작이 발생합니다.
Spectral

답변:


92

현재 객체 ID를 테스트하고 있다는 점에 유의하세요 ( 두 피연산자가 메모리에서 동일한 객체로 표현되는 경우 is에만 반환 True됩니다.이 경우와 같게 비교되는 두 객체가 항상 그런 것은 아닙니다 ==). 의도적으로이 작업을 수행하는 경우 코드를 다음과 같이 다시 작성할 수 있습니다.

some_dict = {key: value for key, value in some_dict.items() 
             if value is not value_to_remove}

그러나 이것은 당신이 원하는 것을 할 수 없습니다.

>>> some_dict = {1: "Hello", 2: "Goodbye", 3: "You say yes", 4: "I say no"}
>>> value_to_remove = "You say yes"
>>> some_dict = {key: value for key, value in some_dict.items() if value is not value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 3: 'You say yes', 4: 'I say no'}
>>> some_dict = {key: value for key, value in some_dict.items() if value != value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 4: 'I say no'}

따라서 !=대신 is not.


2
그게 사전 압축인가요? 언제 추가 되었습니까?
Buttons840 2011 년

4
some_dict.iteritems()여기에서 사용 하고 가독성을 위해 별도의 줄에 forif문을 입력 할 수 있습니다.
jfs

3
파이썬 2.7에 사전 이해가 추가되었다고 생각합니다.
mithrandi 2011 년

2
@JF Sebastian : 저는 Python 3을 사용하고 iteritems있으며 현재 items. Python 2.7에서는 iteritems()실제로 더 좋습니다.
Tim Pietzcker 2011 년

1
@ Buttons840 이들은 PEP 274 또는 사전 디스플레이 에서 dict comprehensions 라고 합니다 . PEP가 말했듯이 2.7 에서는 백 포트 된 3.x 위업으로 추가되었습니다 . 또는 dict()적절한 생성기 표현식 (2.4)을 제공 할 수 있습니다 . meta : 여기 에서 물건을 찾기 위해 peps검색 할 수 있습니다 .
n611x007 2014 년

120

dict.pop(key[, default])방법을 사용하면 키를 알고있을 때 항목을 제거 할 수 있습니다. 항목을 제거하면 키의 값을 반환하고 그렇지 않으면 전달 된 것을 반환합니다 default. 문서를 참조하십시오 . '

예:

>>> dic = {'a':1, 'b':2}
>>> dic
{'a': 1, 'b': 2}
>>> dic.pop('c', 0)
0
>>> dic.pop('a', 0)
1
>>> dic
{'b': 2}

4
OP는 언제 키를 알 수
없는지 묻습니다.

52
a = {'name': 'your_name','class': 4}
if 'name' in a: del a['name']

OP는 언제 키를 알 수 없는지 묻습니다. 이 대답은 키가 알려져 있다고 가정합니다.
Jean-François Corbett

42

delpop () 간의 간단한 비교 :

import timeit
code = """
results = {'A': 1, 'B': 2, 'C': 3}
del results['A']
del results['B']
"""
print timeit.timeit(code, number=100000)
code = """
results = {'A': 1, 'B': 2, 'C': 3}
results.pop('A')
results.pop('B')
"""
print timeit.timeit(code, number=100000)

결과:

0.0329667857143
0.0451040902256

따라서 delpop () 보다 빠릅니다 .


6
그러나 성능 차이는 크지 않으며 예외 발생을 피하려면 두 번째 인수를 제공 할 수 있습니다 pop()(위의 @ n-1-1이 수행 한 것처럼) del. 이는 연산자 옵션이 아닙니다 .
Alex Dupuy

1
질문에 부수적이지만 나는 또한 이해하기 위해 고군분투했습니다 timeit. 이 명확한 예에 감사드립니다.
Adam_G

OP는 언제 키를 알 수 없는지 묻습니다. 이 대답은 키가 알려져 있다고 가정합니다.
Jean-François Corbett

7

items()목록을 반환하고 반복하는 목록이므로 루프에서 dict를 변경하는 것은 여기서 중요하지 않습니다. iteritems()대신 사용 하는 경우 루프에서 dict를 변경하는 것은 문제가 될 수viewitems() 있으며 Python 2.7 에서도 마찬가지입니다 .

값으로 dict에서 항목을 제거하는 더 좋은 방법을 생각할 수 없습니다.


7

제거가 필요한 키 목록을 작성한 다음 제거합니다. 간단하고 효율적이며 딕셔너리를 반복하고 변경하는 것과 관련된 문제를 방지합니다.

keys_to_remove = [key for key, value in some_dict.iteritems()
                  if value == value_to_remove]
for key in keys_to_remove:
    del some_dict[key]

OP는 언제 키를 알 수 없는지 묻습니다. 이 대답은 키가 알려져 있다고 가정합니다.
Jean-François Corbett


1
y={'username':'admin','machine':['a','b','c']}
if 'c' in y['machine'] : del y['machine'][y['machine'].index('c')]

0

제안한대로 반복하는 동안 사전에서 항목을 삭제하는 데 아무런 문제가 없습니다. 동시에 동일한 사전을 사용하는 여러 스레드에주의하십시오. KeyError 또는 기타 문제가 발생할 수 있습니다.

물론 http://docs.python.org/library/stdtypes.html#typesmapping 의 문서를 참조하십시오.


for k,v in d.iteritems(): del d[k]줄 것이다 RuntimeError: dictionary changed size during iteration. mithrandi의 설명을 참조하십시오.
Buttons840 2011 년

1
물론 d.iteritems ()는 원래 포스터가 반복되는 방식이 아니며 내 대답에서 언급 한 것이 아닙니다.
Thane Anthem

0

이것이 내가 할 방법입니다.

for key in some_dict.keys():
    if some_dict[key] == item_to_remove:
        some_dict.pop(key)
        break
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.