web-dev-qa-db-ja.com

Python辞書の理解

Pythonで辞書の内包表記を作成することは可能ですか(キー用)。

リスト内包表記がなくても、次のように使用できます。

l = []
for n in range(1, 11):
    l.append(n)

これをリスト内包表記に短縮することができます:l = [n for n in range(1, 11)]

しかし、辞書のキーを同じ値に設定したいとしましょう。できます:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

私はこれを試してみました:

d = {}
d[i for i in range(1, 11)] = True

しかし、私はSyntaxErrorforを得ます。

さらに(私はこの部分は必要ありませんが、ただ疑問に思っています)、辞書のキーを次のようにたくさんの異なる値に設定できます。

d = {}
for n in range(1, 11):
    d[n] = n

これは辞書の理解で可能ですか?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

これはまたSyntaxErrorforを上げます。

346
Rushy Panchal

Python 2.7+には 辞書の内包表記があります しかし、それらはあなたが試しているようには動作しません。リスト内包表記のように、それらは new 辞書を作ります。既存の辞書にキーを追加するためにそれらを使用することはできません。また、キーと値を指定する必要がありますが、もちろん、ダミー値を指定することもできます。

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

すべてをTrueに設定したい場合は、

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

あなたが求めているのは、既存の辞書に一度に複数のキーを設定する方法です。そのための直接的な近道はありません。あなたはすでに示したようにループすることもできますし、あるいは辞書内包表記を使って新しい値で新しい辞書を作成してからoldDict.update(newDict)を実行して新しい値を古い辞書にマージすることもできます。

467
BrenBarn

dict.fromkeys classメソッドを使えます。

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

これは、すべてのキーが同じ値にマップされる辞書を作成するための最速の方法です。

しかし do not 可変オブジェクトでこれを使う

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

実際にすべてのキーを初期化するためにneedを使わないのであれば、defaultdictも便利です。

from collections import defaultdict
d = defaultdict(True)

2番目の部分に答えるために、辞書理解はあなたが必要としているものだけです:

{k: k for k in range(10)}

おそらくこれをしてはいけませんが、__missing__をオーバーライドするとdictのように動作するdefaultdictのサブクラスを作成することもできます。

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}
145
mgilson
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
25
NPE

@mgilsonのコメントがとても気に入っています。2つのイテラブルがあり、一方はキーに対応し、もう一方は値に対応している場合、次のこともできます。

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(Zip(keys, values))

与える

d = {'a':1、 'b':2、 'c':3}

19
ehontz

タプルのリストにdict()を使用すると、この解決法では、同じ長さであれば、各リストに任意の値を入れることができます。

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])
11
Bryan

辞書内包表記を使用してリスト内の単語の出現数を数えるこの例を考えてみましょう。

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

そしてその結果は

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}
10
adonese

リスト内包表記の主な目的は、元のリストを変更または破壊することなく、別のリストに基づいて新しいリストを作成することです。

書く代わりに

    l = []
    for n in range(1, 11):
        l.append(n)

または

    l = [n for n in range(1, 11)]

あなただけ書くべき

    l = range(1, 11)

上の2つのコードブロックでは、新しいリストを作成し、それを繰り返して各要素を返すだけです。これはリストコピーを作成するための単なる高価な方法です。

別の辞書に基づいてすべてのキーを同じ値に設定した新しい辞書を作成するには、次のようにします。

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

あなたが書くときSyntaxErrorを受け取っています

    d = {}
    d[i for i in range(1, 11)] = True

基本的に言っているのは、「自分のキー 'i for iの範囲(1、11)'をTrueに設定する」および「私のiの範囲(1、11)内のi」は有効なキーではなく、構文エラーです。サポートされているリストをキーにしないのであれば、次のようにします。

    d[[i for i in range(1, 11)]] = True

ではなく

    d[i for i in range(1, 11)] = True

しかし、リストはハッシュ可能ではないので、あなたはそれらを辞書キーとして使うことはできません。

7
Bonifacio2