web-dev-qa-db-ja.com

辞書から要素を削除する

Pythonで辞書から項目を削除する方法はありますか?

さらに、コピーを返すために辞書からアイテムを削除するにはどうすればよいですか(つまり、オリジナルを変更しないでください)。

1094
richzilla

delステートメント は要素を削除します。

del d[key]

ただし、これにより既存の辞書が変更されるため、同じインスタンスを参照している他のユーザーに対して辞書の内容が変更されます。 new 辞書を返すには、辞書のコピーを作成します。

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

dict()コンストラクタは シャローコピー を作成します。ディープコピーを作成するには、 copyモジュール を参照してください。


すべての辞書del/assignment/etcのコピーを作成することに注意してください。これは、一定時間から線形時間へ、そしてまた線形空間を使用することを意味します。ちょっとした言葉では、これは問題にはなりません。しかし、大きな辞書のコピーをたくさん作成しようと思っているのなら、( この答え で説明されているように)おそらくHAMTのような異なるデータ構造が必要です。

1441
Greg Hewgill

pop は辞書を変更します。

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}

あなたがオリジナルを保存したいならば、あなたはそれを単にコピーすることができました。

191
Crystal

私はあなたの解決策がそれをする最善の方法だと思います。しかし、別の解決策が必要な場合は、次のように、指定したキーを含めずに古い辞書のキーを使用して新しい辞書を作成できます。

>>> 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'}
65
utdemir

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
50
arussell84

いい答えはたくさんありますが、一つ強調したいと思います。

辞書から項目を削除するには 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()はそれ自体が複雑でオーバーヘッドの原因となる関数であるため、delinチェックと一緒に使用すると、 わずかに より高速になる可能性があります。通常はそうではないので、デフォルト値を持つ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}
40
Nikita
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

結果:d = {1: 2, '2': 3}

17
satels

……コピーを返すために辞書からアイテムを削除するにはどうしたらいいですか(つまり、オリジナルを変更しないでください)。

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')はまさにその質問が求めているものです。

dictlistのような変更可能なデータ構造がpmapに埋め込まれている場合でも、エイリアシングの問題があります。それを解決するには、pmapsとpvectorsを埋め込んでください。


1. HAMTはScala、Clojure、Haskellのような言語でも人気があります。ロックフリーのプログラミングやソフトウェアのトランザクションメモリで非常にうまく機能するからですが、どちらもPythonにはあまり関係ありません。

2.実際、 is はstdlibにあり、 contextvars の実装で使用されます。 先に撤回されたPEPがその理由を説明しています。 しかし、これはライブラリの隠された実装の詳細であり、パブリックコレクション型ではありません。

13
abarnert

単にdel d ['key']を呼び出してください。

しかしながら、プロダクションでは、 'key'がdに存在するかどうかをチェックすることは常に良い習慣です。

if 'key' in d:
    del d['key']
13
Khanh Hua

いいえ、他に方法はありません

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

ただし、わずかに変更された辞書のみのコピーを作成することは、比較的大きなメモリ要求が発生するため、おそらくお勧めできません。 (必要ならば)古い辞書を記録してそれを修正するのが普通です。

7
phihag

これがトップレベルのデザインアプローチです。

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}

それが役立つことを願っています!

5
bishop
>>> 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をチェックします。

5
tMC
# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)
4
daino3

以下のコードスニペットは間違いなくあなたを助けるでしょう、私はコードを理解するのを助けるであろう各行にコメントを加えました。

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}
3
Mayur Agarwal

これはリスト内包表記を使った別のバリエーションです。

original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.iteritems() if v)
# result should be {'b': 'Some'}

アプローチはこの記事からの答えに基づいています: 辞書から空の文字列を持つキーを削除する効率的な方法

2
BigBlueHat
    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)
0
Schlator