Dict

Dictionary (辞書, Dict) は、 Key と Value (値)を対応づけるデータ構造です。連想配列 (associative array) とも言われます。 Java では MapHashMap などが対応します。

{'key0': 'val0',  'key1': 'val1' }

主な用途は2通りです。

  • あるデータの複数の属性を表すときに使う。例えば、ある学生の氏名や住所、メールアドレスなどの複数の属性を列挙したい。
  • 複数の要素がある集合に属していて、そのキーと要素を結びつける。例えば、あるクラスの学生ID (key) と各学生の情報(value) を結びつけるとか、商品番号 (key) と商品情報 (value) とかね。

あと、dict に含まれる key を検索するときの平均計算量は O(1) のようです(参考)。

以下、プログラムにおける使い方を簡単にまとめます(プログラム)。

初期化

dct = {'key0': 'val0',  'key1': 'val1' }
print(dct)  # {'key0': 'val0', 'key1': 'val1'}
dct2 = dict(key0='val0', key1='val1')
print(dct2) # {'key0': 'val0', 'key1': 'val1'}

要素アクセス

key を使って value を検索するときに使います。

print(dct['key1'])  # val1
print(dct.get('key1'))   # val1
print('key2' in dct)  # key に含まれるか、出力 False
# print(dct['key2']) 例外発生
print(dct.get('key2'))  # None
print(dct.get('key2', 'valX'))  # valX (default value)

要素追加・削除

dct['key2'] = 'val2'  # 挿入
print(dct)  # {'key0': 'val0', 'key1': 'val1', 'key2': 'val2'}

dct['key1'] = {}  # 挿入(dict を値として上書き)
print(dct)  # {'key0': 'val0', 'key1': {}, 'key2': 'val2'}
dct['key1']['keyA'] = 'valA'
print(dct)  # {'key0': 'val0', 'key1': {'keyA': 'valA'}, 'key2': 'val2'}
dct['key1']['keyB'] = 'valB'
print(dct)  # {'key0': 'val0', 'key1': {'keyA': 'valA', 'keyB': 'valB'}, 'key2': 'val2'}

dct.pop('key2') # 削除
print(dct)  # {'key0': 'val0', 'key1': {'keyA': 'valA', 'keyB': 'valB'}}

内包表記を用いた生成

# loop 操作
# 内包表記を用いた dict 生成
# range(4) の要素 i に対し i * i : i なる key, value で初期化
dct = {i * i: i for i in range(4)}
print(dct)  # {0: 0, 1: 1, 4: 2, 9: 3}

key, values の取得とループ処理

print(dct.keys())  # dict_keys([0, 1, 4, 9])
print(list(dct.keys()))  # [0, 1, 4, 9]
print(dct.values())  # dict_values([0, 1, 2, 3])
print(dct.items())  # dict_items([(0, 0), (1, 1), (4, 2), (9, 3)])

# key に対して loop
for key in dct.keys():
    print(f'A:: key:{key}, value: {dct[key]} ')
# value に対して loop
for v in dct.values():
    print(f'B:: value: {v}')
# key, value の組に対して loop
for k, v in dct.items():
    print(f'C:: key:{k}, value: {v} ')

# 内包表記でも key, value 利用可能
dct3 = {f'key{k}': f'v{v}' for k, v in dct.items()}
print(dct3)

dict の同一性判定

互いに同じ key-value から構成されていれば同一ですが、key-value の表記順は関係ありません。

a = {'name': 'Taro', 'age': 12}
b = {'name': 'Taro', 'age': 22}
print(f'a==b: {a == b} for a: {a} and b: {b}')
# a==b: False for a: {'name': 'Taro', 'age': 12} and b: {'name': 'Taro', 'age': 22}
a['age'] = 22
print(f'a==b: {a == b} for a: {a} and b: {b}')
# a==b: True for a: {'name': 'Taro', 'age': 22} and b: {'name': 'Taro', 'age': 22}
c = {'age': 22, 'name': 'Taro'}
print(f'a==c: {a == c} for a: {a} and c: {c}')
# a==c: True for a: {'name': 'Taro', 'age': 22} and c: {'age': 22, 'name': 'Taro'}

dict のソート

dict 自身はソートされる訳ではないが、 items() で取得した k,v の組(tuple) の「あつまり」を、 sorted() でソート済みリストにすることはできる

dict0 = {
    'studentA': 78,
    'studentC': 80,
    'studentB': 82,
    'studentD': 84
}
print(sorted(dict0.items()))  # [('studentA', 78), ('studentB', 82), ('studentC', 80), ('studentD', 84)]

key-value の組の並びなので、ソート順を変えたい場合、tuple に対して key 関数を作る必要がある。 以下は、value (成績)の降順にソートしたい場合。

def my_key(pair):
    k0, v0 = pair
    return -v0

で、利用する方は、こんな感じ

print(sorted(dict0.items(), key=my_key))  # [('studentD', 84), ('studentB', 82), ('studentC', 80), ('studentA', 78)]

Read more