【Python】Pythonの辞書型活用法メモ

## 辞書型とは

**辞書**は、**キー**(名前)と値のペアを要素として管理できるデータ型。要素につけた名前(キー)を使って参照する。

- **キーと値のペア**の集合。キーに対応する値を取得できる。
- キーは、イミュータブル(変更不可)なものしか指定できない。
- 同じキーは1つだけもてる。複数追加すると上書きする。
- マップや連想配列と呼ぶこともある

**辞書の作成**

```
変数 = {キー1 : 値1, キー2 : 値2, ...}
```

辞書の要素は`キー: 値`のペアで構成される。キーに使うのは、文字列でも数値でも可能。

辞書の要素は書き換え可能(ミュータブル)だが、キーだけの変更はできない(キーはイミュータブル)。変更する場合は要素(キー:値)ごと削除して、新しい要素を追加することになる。



## 辞書型基礎編
### | 辞書を作成する

```python
player = {'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}
```

### | 空の辞書に追加する方法

```python
player = {}
# player = dict() 上と同じ意味
player['クリステファン・ローディ'] = 'FW'
print(player)
player['ジネディーヌ・ジダン'] = 'OMF'
print(player)
```

```py:実行結果
{'クリステファン・ローディ': 'FW'}
{'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF'}
```

### | キーの値を変更

```python
player = {'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}
player['クリステファン・ローディ'] = 'CF'
print(player)
```

```py:実行結果
{'クリステファン・ローディ': 'CF', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}
```

### | 値の参照と要素の削除

```python
print(player['ラブレル・ガガ'])
del player['ラブレル・ガガ']
print(player)
```

```py:実行結果
CDF
{'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF'}
```



## 辞書の主なメソッド

| メソッド等                            | 説明                                                         |
| :------------------------------------ | :----------------------------------------------------------- |
| `get(key, default=None)`              | `key`に対応する値を取得。存在しないときは、`default`を返す。 |
| `clear()`                             | 全ての要素を削除。                                           |
| `copy()`                              | コピーを作成。                                               |
| `pop(key[, default])`                 | `key`に対応する要素を削除し値を返す。存在しないときは、`default`が指定されていればそれを返し、なければエラー（KeyError）になる。 |
| `popitem()`                           | 最後に追加された要素を削除(Python3.7以降)し、キーと値のタプルを返す。空だとエラー（KeyError）になる。 |
| `setdefault(key, default=None)`       | `key`が存在するときは対応する値を返す。存在しないときは`key`を`default`で設定し、`default`を返す。 |
| `update(other)`                       | 別の辞書`other`の要素全てを追加。                            |
| `dict.fromkeys(iterable, value=None)` | `iterable`の要素をキーに、値を`value`として辞書を作成。      |



### | `dict.fromkeys(iterable, value=None)`

```python
names = ['クリステファン・ローディ', 'ジネディーヌ・ジダン', 'ラブレル・ガガ']
player = dict.fromkeys(names, 'ポケサカ')
print(player)
```

```py:実行結果
{'クリステファン・ローディ': 'ポケサカ', 'ジネディーヌ・ジダン': 'ポケサカ', 'ラブレル・ガガ': 'ポケサカ'}
```

リストをキーとして、`''ポケサカ'`を値とした辞書がつくられた。



### | `get(key, default=None)`

```python
print(player.get('デルビー・ベルコム', -1))
print(player.get('クリステファン・ローディ', -1))
```

```:実行結果
-1
ポケサカ
```

キーが存在しない場合は-1を返し、存在する場合はその値を返した。



### | `setdefault(key, default=None)`

```python
print(player.setdefault('デルビー・ベルコム', 'ポケサカ'))
print(player)
print(player.setdefault('デルビー・ベルコム', 'ウイイレ'))
```

```:実行結果
ポケサカ
{'クリステファン・ローディ': 'ポケサカ', 'ジネディーヌ・ジダン': 'ポケサカ', 'ラブレル・ガガ': 'ポケサカ', 'デルビー・ベルコム': 'ポケサカ'}
ポケサカ
```



### | `update(other)`

```python
wiele = {'クリスティアーノ・ロナウド': 'ウイイレ'}
player.update(wiele)
print(player)
```

wieleの辞書が追加された。



### | `pop(key), popitem()`

```python
print(player.pop('クリスティアーノ・ロナウド'))
print(player)
print(player.popitem())
print(player)
```

```py:実行結果
ウイイレ
{'クリステファン・ローディ': 'ポケサカ', 'ジネディーヌ・ジダン': 'ポケサカ', 'ラブレル・ガガ': 'ポケサカ', 'デルビー・ベルコム': 'ポケサカ'}
('デルビー・ベルコム', 'ポケサカ')
{'クリステファン・ローディ': 'ポケサカ', 'ジネディーヌ・ジダン': 'ポケサカ', 'ラブレル・ガガ': 'ポケサカ'}
```



### | clear()

```python
player.clear()
print(player)
```

```py:実行結果
{}
```



## イテラブルを返すメソッド

※イテラブル：for文で繰り返せるオブジェクトまたはそのクラス

| メソッド   | 説明                                               |
| :--------- | :------------------------------------------------- |
| `keys()`   | キーを要素とするイテラブルを返します。             |
| `values()` | 値を要素とするイテラブルを返します。               |
| `items()`  | キーと値のタプルを要素とするイテラブルを返します。 |

```python
player = {'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}

# キーだけを取り出す
for key in player.keys():
    print(key)

# 値だけを取り出す    
for value in player.values():
    print(value)

# キーと値をセットで取り出す
for key, value in player.items():
    print('{}: {}'.format(key, value))
```

```:実行結果
クリステファン・ローディ
ジネディーヌ・ジダン
ラブレル・ガガ
FW
OMF
CDF
クリステファン・ローディ: FW
ジネディーヌ・ジダン: OMF
ラブレル・ガガ: CDF
```



## 辞書型応用編

### | さまざまな辞書の作成方法

```python
player = {'FW': 1, 'OMF': 2, 'CDF': 3}
player = dict(FW=1, OMF=2, CDF=3)
player = dict([('FW', 1), ('OMF', 2), ('CDF', 3)])
player = dict(**{'FW': 1, 'OMF': 2, 'CDF': 3})
```

上記の4通りはすべて同じ辞書を作る



### | 2つのリストから辞書を作る

2つのリストの一方の要素をキー、もう一方のリストの要素を値にした辞書をつくることができる。

```python
names = ['クリステファン・ローディ', 'ジネディーヌ・ジダン', 'ラブレル・ガガ']
positions = ['FW', 'OMF', 'CDF']
player = dict(zip(names, positions))
print(player)
```

```py:実行結果
{'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}
```



### | 内包表記で辞書を作成する

2つのリストを内包表記を使って辞書にする。

```python
names = ['クリステファン・ローディ', 'ジネディーヌ・ジダン', 'ラブレル・ガガ']
positions = ['FW', 'OMF', 'CDF']
player = {k: v for (k, v) in zip(names, positions)}
print(player)
```

```py:実行結果
{'クリステファン・ローディ': 'FW', 'ジネディーヌ・ジダン': 'OMF', 'ラブレル・ガガ': 'CDF'}
```



### | キーの最大値とその時の値を取得

キーの最大値が`'E'`, 値の最大値が`5`となる辞書で考える。

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'A':4}
max_key = max(d)
print(max_key)
print(d[max_key])
```

```py:実行結果
E
1
```



### | 値の最大値を取得

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'A':4}
max_value = max(d.values())
print(max_value)
```

```py:実行結果
5
```



### | キーが最大となるキーと値のペアを取得

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'A':4}
max_item = max(d.items())
print(max_item)
```

```py:実行結果
('E', 1)
```



### | 値が最大となるときのキーを取得

- **max()のkeyパラメータを使う方法**

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'A':4}
max_v_k = max(d.items(), key = lambda x:x[1])[0]
print(max_v_k)
```

```py:実行結果
B
```



- **リスト内包表記を使う方法**

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'A':4}
max_v_k = max((v, k) for k, v in d.items())[1]
print(max_v_k)
```

```py:実行結果
B
```

これらの方法は、最大値が複数ある場合は注意が必要になる。
keyパラメータを使う方法と、リスト内包表記を使う方法で結果が異なる場合がある。

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'F': 5, 'A':4}
# keyパラメータを使う方法
max_1 = max(d.items(), key = lambda x:x[1])[0]
print(max_1)

# リスト内包表記を使う方法
max_2 = max((v, k) for k, v in d.items())[1]
print(max_2)
```

```py:実行結果
B
F
```

**Keyパラメータを使った場合**は、辞書の値(value)の最大値のうち最初にヒットしたキー(key)を出力するのに対し、**リスト内包表記を使った場合**は、タプルの２番めの要素（上記例では”k”）が比較され、それが大きい方が出力される。



### | 値が最大値の時のキーすべて取得

```python
d = {'E':1, 'D':2, 'C':3, 'B':5, 'F': 5, 'A':4}
maxes = [k for k, v in d.items() if v == max(d.values())]
print(maxes)
```

```py:実行結果
['B', 'F']
```



### | 辞書を値とする辞書を作成

キーに背番号、辞書型を値としてもつ辞書を作成

```python
player = {
    7: {'name': 'クリステファン・ローディ', 'attack': 409},
    9: {'name': 'ルーズ・スレネス', 'attack': 397},
    10: {'name': 'ジネディーヌ・ジダン', 'attack': 356}
}
print(player)
```

```py:実行結果
{7: {'name': 'クリステファン・ローディ', 'attack': 409}, 9: {'name': 'ルーズ・スレネス', 'attack': 397}, 10: {'name': 'ジネディーヌ・ジダン', 'attack': 356}}
```

```python
print(player[7])
print(player[9]['name'])
print(player[10]['attack'])
```

```:実行結果
{'name': 'クリステファン・ローディ', 'attack': 409}
ルーズ・スレネス
356
```



**attackの値が最大の選手の背番号を取得する**

```python
player = {
    7: {'name': 'クリステファン・ローディ', 'attack': 409},
    9: {'name': 'ルーズ・スレネス', 'attack': 397},
    10: {'name': 'ジネディーヌ・ジダン', 'attack': 356}
}
attack = {player[n]["attack"]: n for n in player.keys()}
max_attack = max(attack.keys())
print(attack[max_attack])
```

```py:実行結果
7
```



## 辞書型活用法

`positions`にチームに所属する選手のポジションが入っている。ポジションごとの選手の人数を辞書teamに入れる。

```python
positions = ['FW', 'MF', 'DF', 'GK', 'MF', 'MF', 'GK', 'FW', 'MF', 'MF', 'DF', 'DF']

team = dict.fromkeys(['FW', 'MF', 'DF', 'GK'], 0)
for position in positions:
    team[position] += 1

for position, num in team.items():
    print('{}: {}人'.format(position, num))
```

```:実行結果
FW: 2人
MF: 5人
DF: 3人
GK: 2人
```

```python
positions = ['CF', 'OMF', 'CDF', 'GK', 'OMF', 'DMF', 'GK', 'ST', 'MF', 'MF', 'SDF', 'SDF', 'WG', 'CF', 'CF', 'GK', 'OMF', 'ST', 'DMF']

team = dict()
for position in positions:
    if position in team:
        team[position] += 1
    else:
        team[position] = 1

for position, num in team.items():
    print('{}: {}人'.format(position, num))
```

```:実行結果
CF: 3人
OMF: 3人
CDF: 1人
GK: 3人
DMF: 2人
ST: 2人
MF: 2人
SDF: 2人
WG: 1人
```

**set型を使うと以下のようにも書ける**

```python
positions = ['CF', 'OMF', 'CDF', 'GK', 'OMF', 'DMF', 'GK', 'ST', 'MF', 'MF', 'SDF', 'SDF', 'WG', 'CF', 'CF', 'GK', 'OMF', 'ST', 'DMF']

team = dict.fromkeys(set(positions), 0)
for position in positions:
    team[position] += 1

for position, num in team.items():
    print('{}: {}人'.format(position, num))
```

```:実行結果
DMF: 2人
CDF: 1人
OMF: 3人
GK: 3人
ST: 2人
SDF: 2人
CF: 3人
MF: 2人
WG: 1人
```