web-dev-qa-db-ja.com

与えられたキーがすで辞書に存在するかどうかを確認し、それをインクリメントします

ある辞書を考えて、その辞書の中の与えられたキーがすでにNone以外の値に設定されているかどうか調べるにはどうすればいいですか?

つまり、これをやりたいのです。

my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

つまり、すでに存在する場合は値を増やしたい、そうでない場合は1に設定します。

261
Ben

探しているのは collections.defaultdict (Python 2.5以降で利用可能)。この

from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

あなたが望むことをするでしょう。

通常のPythonのdictsの場合、与えられたキーに値がなければ、辞書にアクセスするときにnotNoneを得ます - KeyErrorが発生します。あなたのコードの代わりに通常のdictを使いたいのであれば

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1
300
dF.

私はこれを1行のコードで行うことを好みます。

 my_dict = {} 
 
 my_dict [some_key] = my_dict.get(some_key、0)+ 1 

辞書にはgetという関数があります。これは2つのパラメータ、つまり必要なキーと、存在しない場合のデフォルト値を取ります。この1行のコードにキーが存在しない場合だけを処理したいため、このメソッドはdefaultdictを使用します。

270

個人的にはsetdefault()を使うのが好きです

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
49
kichik

そのためにはkey in dictイディオムが必要です。

if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

ただし、(dFが推奨するように)defaultdictを使用することをおそらく検討する必要があります。

48
Eli Bendersky

その辞書の特定のインデックスが既にNone以外の値に設定されているかどうかはどうすればわかりますか」という質問に答えるには、この:

try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

これはすでに呼び出されているEAFPの概念に準拠しています(許しを求めるよりも簡単です)。また、key in my_dict and my_dict[key] is not Noneと同じように辞書内の重複キー検索も回避できます。

あなたが提起した実際の問題、すなわちもしあればintをインクリメントするか、そうでなければデフォルト値に設定するためには、

my_dict[key] = my_dict.get(key, default) + 1

andrew Wilkinsonの答えのように。

あなたがあなたの辞書に修正可能なオブジェクトを格納しているならば、3番目の解決策があります。これの一般的な例は マルチマップ です。ここではキーの要素のリストを保存します。その場合は、次のものを使用できます。

my_dict.setdefault(key, []).append(item)

Keyの値が辞書に存在しない場合、setdefaultメソッドはそれをsetdefaultの2番目のパラメータに設定します。これは標準のmy_dict [key]と同じように動作し、キーの値(新しく設定された値かもしれません)を返します。

18
nd.

Cgoldbergと同意しました。やり方は:

try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

そのため、上記のようにするか、他の人が示唆しているようにデフォルトの辞書を使用してください。 if文を使わないでください。それはPythonicではありません。

13
ryeguy

多くの答えからわかるように、いくつかの解決策があります。 LBYLの1つのインスタンス(あなたが跳躍する前に見てください)はまだ言及されていません、has_key()メソッド:

my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __== '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict
11
bortzmeyer

あなたがそれをやろうとしている方法は、あなたがあなたの値を増加させようとする前に条件をチェックしているので、LBYLと呼ばれます。

もう1つのアプローチはEAFPと呼ばれます(許しを求めるよりも許しを求めるほうが簡単です)。その場合は、単に操作を試す(値を増やす)だけです。失敗した場合は、例外をキャッチして値を1に設定します。これはもう少しPythonicの方法です(IMO)。

http://mail.python.org/pipermail/python-list/2003-May/205182.html

7
Corey Goldberg

これは直接質問に答えるものではありませんが、私には、 collections.Counter の機能が必要になるかもしれません。

from collections import Counter

to_count = ["foo", "foo", "bar", "baz", "foo", "bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

これは出力になります

Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times
5

少し遅れますが、これでうまくいくはずです。

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
5
Bob

これは私が最近この問題を解決するために思い付いたものです。これは setdefault 辞書メソッドに基づいています。

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1
3
Igor Gai

私はそれを探していました、それがウェブ上でそれを見つけなかったそしてそれからTry/Errorで私の運を試してみてそれを見つけました

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1
1
AbhishekKr