파이썬에서 사전에서 항목을 삭제하는 방법이 있습니까?
또한 사전에서 항목을 삭제하여 사본을 반환하려면 어떻게해야합니까 (예 : 원본을 수정하지 않음)?
답변
del
문 요소를 제거합니다 :
del d[key]
그러나 이는 기존 사전을 변경하여 동일한 인스턴스에 대한 참조가있는 다른 사용자의 사전 내용을 변경합니다. 새 사전 을 반환하려면 사전을 복사하십시오.
def removekey(d, key):
r = dict(d)
del r[key]
return r
dict()
생성자는 만드는 얕은 사본을 . 딥 카피를 만들려면 copy
모듈을 참조하십시오 .
모든 dict del
/ assignment / etc에 대해 사본을 작성하십시오 . 일정 시간에서 선형 시간으로 이동하고 선형 공간을 사용한다는 의미입니다. 작은 받아쓰기의 경우 문제가되지 않습니다. 그러나 큰 dicts의 사본을 많이 만들 계획이라면 HAMT와 같은 다른 데이터 구조를 원할 것입니다 ( 이 답변에 설명되어 있음 ).
답변
pop
사전을 변경합니다.
>>> lol = {"hello": "gdbye"}
>>> lol.pop("hello")
'gdbye'
>>> lol
{}
원본을 보관하려면 복사 만하면됩니다.
답변
귀하의 솔루션이 최선의 방법이라고 생각합니다. 그러나 다른 솔루션을 원하면 다음과 같이 지정된 키를 포함하지 않고 이전 사전의 키를 사용하여 새 사전을 만들 수 있습니다.
>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}
답변
델 문은 당신이 찾고있는 것입니다. ‘bar’라는 키가있는 foo라는 사전이있는 경우 다음과 같이 foo에서 ‘bar’를 삭제할 수 있습니다.
del foo['bar']
이렇게하면 조작중인 사전이 영구적으로 수정됩니다. 원래 사전을 유지하려면 사전에 사본을 작성해야합니다.
>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}
dict
호출은 얕은 복사본을 만듭니다. 깊은 사본을 원하면을 사용하십시오 copy.deepcopy
.
편의를 위해 복사하여 붙여 넣을 수있는 방법은 다음과 같습니다.
def minus_key(key, dictionary):
shallow_copy = dict(dictionary)
del shallow_copy[key]
return shallow_copy
답변
좋은 답변이 많이 있지만 한 가지만 강조하고 싶습니다.
둘 다 사용할 수있는 dict.pop()
방법 및보다 일반적인 del
문을 사전에서 항목을 제거 할 수 있습니다. 둘 다 원래 사전을 변경하므로 복사해야합니다 (아래 세부 사항 참조).
그리고 그들에게 KeyError
제공하는 키가 사전에 없으면 두 가지 모두 a를 발생시킵니다.
key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove] # Raises `KeyError: 'c'`
과
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove) # Raises `KeyError: 'c'`
당신은 이것을 처리해야합니다 :
예외를 캡처하여 :
key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
del d[key_to_remove]
except KeyError as ex:
print("No such key: '%s'" % ex.message)
과
key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
d.pop(key_to_remove)
except KeyError as ex:
print("No such key: '%s'" % ex.message)
확인을 수행하여 :
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
del d[key_to_remove]
과
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
d.pop(key_to_remove)
그러나 pop()
훨씬 더 간결한 방법이 있습니다-기본 반환 값을 제공하십시오.
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None) # No `KeyError` here
pop()
키 값을 제거하기 위해 사용하지 않는 한 필요하지 않은 것을 제공 할 수 있습니다 None
. 검사 del
와 함께 사용 하면 오버 헤드를 일으키는 자체 합병증이있는 기능 으로 인해 약간 빠릅니다 . 일반적으로 그렇지 않으므로 기본값으로 충분합니다.in
pop()
pop()
주요 질문에 대해서는 사전 사전을 복사하여 원래 사전을 저장하고 키를 제거하지 않고 새 사전을 만들어야합니다.
여기에있는 다른 사람들은을 사용하여 전체 (깊은) 복사본을 만들 것을 제안 copy.deepcopy()
합니다. 이는 과잉 copy.copy()
이거나 “보통”(얕은) 복사본 이거나 또는를 사용하는 dict.copy()
것으로 충분할 수 있습니다. 사전은 객체에 대한 참조를 키 값으로 유지합니다. 따라서 사전에서 키를 제거하면 참조되는 객체가 아니라이 참조가 제거됩니다. 메모리에 객체에 대한 다른 참조가 없으면 가비지 수집기에서 객체 자체를 나중에 자동으로 제거 할 수 있습니다. 딥 카피를 만들려면 얕은 카피에 비해 더 많은 계산이 필요하므로 카피를 만들고 메모리를 낭비하며 GC에 더 많은 작업을 제공하여 코드 성능이 떨어지며 때로는 카피가 충분합니다.
그러나 변경 가능한 객체를 사전 값으로 가지고 나중에 키없이 반환 된 사전에서 수정하려는 경우 딥 카피를 만들어야합니다.
얕은 사본으로 :
def get_dict_wo_key(dictionary, key):
"""Returns a **shallow** copy of the dictionary without a key."""
_dict = dictionary.copy()
_dict.pop(key, None)
return _dict
d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"
new_d = get_dict_wo_key(d, key_to_remove)
print(d) # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d) # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d) # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3, 100], "b": 2222}
깊은 사본으로 :
from copy import deepcopy
def get_dict_wo_key(dictionary, key):
"""Returns a **deep** copy of the dictionary without a key."""
_dict = deepcopy(dictionary)
_dict.pop(key, None)
return _dict
d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"
new_d = get_dict_wo_key(d, key_to_remove)
print(d) # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d) # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d) # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d) # {"a": [1, 2, 3, 100], "b": 2222}
답변
… 사전에서 항목을 삭제하여 사본을 반환하려면 어떻게해야합니까 (예 : 원본을 수정하지 않음)?
A dict
는 이것에 사용할 잘못된 데이터 구조입니다.
물론, dict을 복사하고 copy에서 튀어 나와서, 새로운 dict를 이해력으로 만드는 것도 마찬가지입니다. 그러나 모든 복사에는 시간이 걸립니다. 일정 시간 작업을 선형 시간 작업으로 대체했습니다. 그리고 한 번에 살아있는 모든 사본은 공간 당 공간, 즉 사본 당 선형 공간을 차지합니다.
같은 다른 데이터 구조는, 해시 배열이 시도를 매핑 , 사용 사례 정확히 이런 종류의 설계 : 추가하거나 요소를 반환에게 사본을 제거 대수 시간에, 원래와 스토리지의 대부분을 공유 . 1
물론 몇 가지 단점이 있습니다. 성능은 일정하지 않고 대수적입니다 (큰 기반 (일반적으로 32-128)이지만). 그리고 비 돌연변이 API를와 동일하게 만들 수 dict
있지만 “돌연변이”API는 분명히 다릅니다. 그리고 무엇보다도 파이썬에는 HAMT 배터리가 포함되어 있지 않습니다. 2
pyrsistent
라이브러리는 파이썬 HAMT 기반 DICT-교체 (및 기타 다양한 유형)의 꽤 튼튼하게 구현 한 것입니다. 또한 기존의 변경 코드를 영구 코드에 가능한 한 매끄럽게 이식 할 수 있는 멋진 진화 API 가 있습니다. 그러나 변경하지 않고 사본을 반환하는 것에 대해 명시 적으로 나타내려면 다음과 같이 사용하십시오.
>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})
그것이 바로 d3 = d1.remove('a')
질문이 요구하는 것입니다.
에 포함 dict
되고에 list
포함 된 가변 데이터 구조가있는 경우 pmap
에도 앨리어싱 문제가 발생합니다. 불변으로 계속 진행하여 pmap
s 및 pvector
s를 포함 시켜서 만 수정할 수 있습니다 .
1. HAMT는 스칼라, 클로저, 하스켈과 같은 언어에서도 인기를 얻었습니다. 잠금이없는 프로그래밍 및 소프트웨어 트랜잭션 메모리와 매우 잘 작동하기 때문입니다.
2. 사실이 있다 의 구현에 사용되는 다음 stdlib에서 HAMT, contextvars
. 이전에 철회 된 PEP는 그 이유를 설명합니다. 그러나 이것은 공개 컬렉션 유형이 아닌 라이브러리의 숨겨진 구현 세부 사항입니다.
답변
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d
결과: d = {1: 2, '2': 3}