Pythonで辞書から項目を削除する方法はありますか?
さらに、コピーを返すために辞書からアイテムを削除するにはどうすればよいですか(つまり、オリジナルを変更しないでください)。
del
ステートメント は要素を削除します。
del d[key]
ただし、これにより既存の辞書が変更されるため、同じインスタンスを参照している他のユーザーに対して辞書の内容が変更されます。 new 辞書を返すには、辞書のコピーを作成します。
def removekey(d, key):
r = dict(d)
del r[key]
return r
dict()
コンストラクタは シャローコピー を作成します。ディープコピーを作成するには、 copy
モジュール を参照してください。
すべての辞書del
/assignment/etcのコピーを作成することに注意してください。これは、一定時間から線形時間へ、そしてまた線形空間を使用することを意味します。ちょっとした言葉では、これは問題にはなりません。しかし、大きな辞書のコピーをたくさん作成しようと思っているのなら、( この答え で説明されているように)おそらく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'}
del文 はあなたが探しているものです。 '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()
methodとより一般的な del
statement の両方)を使用することができます。両方ともオリジナルの辞書を変更するので、コピーを作成する必要があります。
そして、両方とも KeyError
を与えているのであれば、辞書に存在していなければ:
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
は不要です。ただし、pop()
はそれ自体が複雑でオーバーヘッドの原因となる関数であるため、del
をin
チェックと一緒に使用すると、 わずかに より高速になる可能性があります。通常はそうではないので、デフォルト値を持つ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}
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d
結果:d = {1: 2, '2': 3}
……コピーを返すために辞書からアイテムを削除するにはどうしたらいいですか(つまり、オリジナルを変更しないでください)。
dict
はこれに使用するのに間違ったデータ構造です。
確かに、辞書をコピーしてコピーからポップすることはできますが、理解したまま新しい辞書を作成することもできますが、コピーには時間がかかります。一定時間操作を線形時間操作に置き換えました。そして、それらすべてのコピーは一度に生きていてスペースを取ります - コピーごとの線形スペース。
ハッシュアレイマッピングの試み のような他のデータ構造はまさにこの種のユースケースのために設計されています:対数時間で要素を追加または削除してコピー を返し、元の とその記憶域を共有します。1
もちろん、いくつかの欠点があります。パフォーマンスは一定ではなく対数的です(ただし、基数が大きい場合は通常32〜128)。そして、あなたは変化しないAPIをdict
と同一にすることができますが、「変化する」APIは明らかに異なります。そして、何よりも、PythonにはHAMTバッテリーは含まれていません。2
pyrsistent
ライブラリーは、Python用のHAMTベースの辞書置換(およびその他のさまざまなタイプ)をかなりしっかりと実装したものです。それは気の利いた 進化した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はScala、Clojure、Haskellのような言語でも人気があります。ロックフリーのプログラミングやソフトウェアのトランザクションメモリで非常にうまく機能するからですが、どちらもPythonにはあまり関係ありません。
2.実際、 is はstdlibにあり、 contextvars
の実装で使用されます。 先に撤回されたPEPがその理由を説明しています。 しかし、これはライブラリの隠された実装の詳細であり、パブリックコレクション型ではありません。
単にdel d ['key']を呼び出してください。
しかしながら、プロダクションでは、 'key'がdに存在するかどうかをチェックすることは常に良い習慣です。
if 'key' in d:
del d['key']
いいえ、他に方法はありません
def dictMinus(dct, val):
copy = dct.copy()
del copy[val]
return copy
ただし、わずかに変更された辞書のみのコピーを作成することは、比較的大きなメモリ要求が発生するため、おそらくお勧めできません。 (必要ならば)古い辞書を記録してそれを修正するのが普通です。
これがトップレベルのデザインアプローチです。
def eraseElement(d,k):
if isinstance(d, dict):
if k in d:
d.pop(k)
print(d)
else:
print("Cannot find matching key")
else:
print("Not able to delete")
exp = {'A':34, 'B':55, 'C':87}
eraseElement(exp, 'C')
目的の辞書とキーを自分の関数に渡して、それが辞書であるかどうか、およびキーが適切であるかどうかを検証します。両方が存在する場合は、辞書から値を削除して残りを表示します。
出力:{'B': 55, 'A': 34}
それが役立つことを願っています!
>>> def delete_key(dict, key):
... del dict[key]
... return dict
...
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>
これはエラー処理を行いません。キーが辞書にあると仮定します。最初にチェックし、そうでない場合はraise
をチェックします。
# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)
以下のコードスニペットは間違いなくあなたを助けるでしょう、私はコードを理解するのを助けるであろう各行にコメントを加えました。
def execute():
dic = {'a':1,'b':2}
dic2 = remove_key_from_dict(dic, 'b')
print(dict2) # {'a': 1}
print(dict) # {'a':1,'b':2}
def remove_key_from_dict(dictionary_to_use, key_to_delete):
copy_of_dict = dict(dictionary_to_use) # creating clone/copy of the dictionary
if key_to_delete in copy_of_dict : # checking given key is present in the dictionary
del copy_of_dict [key_to_delete] # deleting the key from the dictionary
return copy_of_dict # returning the final dictionary
あるいはdict.pop()を使うこともできます。
d = {"a": 1, "b": 2}
res = d.pop("c") # No `KeyError` here
print (res) # this line will not execute
またはより良いアプローチは
res = d.pop("c", "key not found")
print (res) # key not found
print (d) # {"a": 1, "b": 2}
res = d.pop("b", "key not found")
print (res) # 2
print (d) # {"a": 1}
これはリスト内包表記を使った別のバリエーションです。
original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.iteritems() if v)
# result should be {'b': 'Some'}
アプローチはこの記事からの答えに基づいています: 辞書から空の文字列を持つキーを削除する効率的な方法
species = {'HI': {'1': (1215.671, 0.41600000000000004),
'10': (919.351, 0.0012),
'1025': (1025.722, 0.0791),
'11': (918.129, 0.0009199999999999999),
'12': (917.181, 0.000723),
'1215': (1215.671, 0.41600000000000004),
'13': (916.429, 0.0005769999999999999),
'14': (915.824, 0.000468),
'15': (915.329, 0.00038500000000000003),
'CII': {'1036': (1036.3367, 0.11900000000000001), '1334': (1334.532, 0.129)}}
次のコードは、dict species
のコピーを作成し、trans_HI
にないアイテムを削除します
trans_HI=['1025','1215']
for transition in species['HI'].copy().keys():
if transition not in trans_HI:
species['HI'].pop(transition)