Python boot camp by Dr.Angela day9

#Dictionary
情報をグループ化してくれる、key指定でvalueを出力する。
[書式] {key：value}

```python3:dict1.py
dict = {
"A":"animal",
"B":"bird",
"C":"camera",
123:"number"        #stringでなければ「""」不要
...
"Z":"zoom",
}                   #追加があればこの位置にすぐに書ける
 
print(dict["C"])
print(dict[123])    #string以外は「""」なしで呼び出し可能

#出力結果
camera      
number
```
上記のようにdictionaryは{}の位置が特徴的。別にこうしなくてもいいけど、通例/一般的に可読性のためこのように書くことが多いらしい。最後は、カッコで閉じる前に「,」で終わること。追加でコード書く際に、__すぐに追加できるように__という配慮かららしい。

####元のコードに追記する以外にdictionaryにkey新規作成 / 既存keyのvalueを編集
dict1.pyの続きに以下を記述

```python3:dict2.py
dictionary["sample"] = "Add other value"   #...(1)
print(dictionary)

dictionary["A"] = "apple"                  #...(2)
print(dictionary)

#出力結果
{'A':'animal', 'B':'bird', ..... , 'sample':'Add other value'}  #(1)の"sample"追記
{'A':'apple', 'B':'bird', ..... , 'sample':'Add other value'}   #(2)の"A"編集
```

####空のdictionaryを作成 / 既存のdictionaryを削除(=空dictを上書きして削除)

```python3:dict3.py
empty_list = []    #空のリスト作成と同様に
empty_dict = {}    #空の辞書も作成可能！

dictionary = {"A":"animal", "B":"bird", ... "Z":"zoom"}
print(dictionary)
dictionary = {}
print(dictionary)

#出力結果
{'A':'animal', 'B':'bird', ..... , 'Z':'zoom'}
{}                 #2回目のprintでは空dictionaryが上書きされて既存の中身が消えた
```
####dictionaryのLoop処理

```python3:dict4.py
for thing in dictionary:
  print(thing)              #keyだけ出力

#出力結果
A
B
...
...
Z      

for thing in dictionary:
  print(dictionary[key])    #valueだけ出力

#出力結果
animal
bird
...
...
zoom  
```

###Mission>> 元データに一切手を加えずに、各データのvalueを変更したい！
一覧データの元データに編集が許されていない場合は往々にしてある。
「生徒+点数の表」から点数に応じて、「生徒+評価の表」にするプログラム。

```python3:score.py
student_scores = {
  "Harry": 81,
  "Ron": 78,
  "Hermione": 99, 
  "Draco": 74,
  "Neville": 62,
}

student_grades = {}
for student in student_scores:
  score = student_scores[student]     #条件分岐に用いる基準を変数に当てる(ここがpoint)
  if score > 90:
    student_grades[student] = "Outstanding"
  elif 80 < score <= 90:
    student_grades[student] = "Exceed"
  elif 70 < score <= 80:
    student_grades[student] = "Acceptable"
  else:
    student_grades[student] = "Fail"

print(student_grades)

#出力結果
{'Harry': 'Exceed', 'Ron': 'Acceptacle', 'Hermione': 'Outstanding', 'Draco': 'Acceptacle', 'Neville': 'Fail'}
```

これで先生も通知表をらくらくつけられそう。

#Nested Dictionary
[書式] {key1:[list], key2:{dict}, ...,}
keyに複数のvalueを紐づけたいときに有用。
####★辞書の中の辞書へアクセス
→__[key1][key2]__でvalue2にアクセス可能！


```python3:dict5.py
travel_log = {
"Japan":["Tokyo","Osaka","Nagoya"],
"France":{cities_visited:["Paris","Lille","Dijion"], "total_visits": 12},
}
print(travel_log["Japan"])                       #辞書のkey1へアクセスしてvalue1出力
print(travel_log["France"]["total_visits"]       #辞書の中の辞書へアクセス

#出力結果
'Tokyo','Osaka','Nagoya'
12
```
####★listの中の辞書へアクセス
→ __[index][key1]__でvalue1へアクセス

```python3:dict6.py
travel_log = [                #2つのlist内にdect_key×3,それぞれのkeyタイプは以下3通り
  {
  "country":"France",                             #string-type
  "cities_visited":["Paris","Lille","Dijion"],    #list-type
  "total_visits":12                               #integer-type
  },
  {
  "county":"Japan",
  "cities_visited":["Tokyo","Osaka","Nagoya"],
  "total_visits":6},
]

print(travel_log[0]["total_visits"])           #listの中の辞書へのアクセス

#出力結果
12
``` 

```python3:dict7.py
travel_log = [
{
  "country": "France",
  "visits": 12,
  "cities": ["Paris", "Lille", "Dijon"]
},
{
  "country": "Germany",
  "visits": 5,
  "cities": ["Berlin", "Hamburg", "Stuttgart"]
},
]

def add_new_country(country_visited, times_visited, cities_visited):
  new_country = {}                            #新規作成用の空dictを作成
  new_country["country"] = country_visited    #新dictのkeyとvalueを紐づけ
  new_country["visits"] = times_visited
  new_country["cities"] = cities_visited
  travel_log.append(new_country)              #travel_logに新dictを追加
                                              #[書式] リスト名.append(追加要素)
add_new_country("Russia", 2, ["Moscow", "Saint Petersburg"])  #新規追加関数の呼び出し
print(travel_log)

#出力結果
[{'country': 'France', 'visits': 12, 'cities': ['Paris', 'Lille', 'Dijon']}, {'country': 'Germany', 'visits': 5, 'cities': ['Berlin', 'Hamburg', 'Stuttgart']}, {'country': 'Russia', 'visits': 2, 'cities': ['Moscow', 'Saint Petersburg']}]
```

```python3:test.py
order = {
"starter": {1: "Salad", 2: "Soup"},
"main": {1: ["Burger", "Fries"], 2: ["Steak"]},
"dessert": {1: ["Ice Cream"], 2: []},
}

print(order["main"][2][0])          #辞書key"main"の中の辞書2の中へアクセス
                                    #疑問->> [0]は必要なのか？
#出力結果
Steak
```
###Mission>> Blind Auction Program
通常のオークションでは、他人がいくらベットしたか分かるようオープンな空間で競りが行われるが、このプログラムでは誰がいくらベットしたのか最後に開示されるまで分からない状態にする。以下2つの技を習得した。
#####★dictionaryからkeyが最大/最小の時のvalueを抽出
#####★dictionaryからvalueが最大/最小の時のvalueを抽出
参考にしたサイト→ https://note.nkmk.me/python-dict-value-max-min/

```python3:auction.py
from replit import clear          #画面を一掃するライブラリを入れる

bids = {}                         #これから作成するlibraryの箱を設ける
finish = False                    #whileでnotにしたい条件をあらかじめFalseにするのは常套句！

while not finish:
  name = input("What is your name? ")
  price = input("What is your bid? $")
  bids[name] = price              #bids(library)の各nameのvalueをpriceと名付け、次行で入力させる
  others = input("Anyone who wants to bid? [yes/no] ")
  if others == "no":
    clear()
    finish = True
  elif others == "yes":
    clear()

contract_price = max(bids.values())      #valueの中で最大のvalueを抽出
winner = max(bids,key=bids.get)          #最大のvalueを持つkeyを抽出
#＜上記を1行で抽出する方法＞
#winner,contract_price = max(bids.items(),key=lambda x:x[1]  ←「:」の前後はスペース不要！参照サイトに誤りあり。
#max()の引数keyにタプルの2要素目を取得(=value)するラムダ式（無名関数）を指定すると、値valueに従っ
#て最大値・最小値が求められる。上記はタプルのアンパックを使用。

print(f"CONGRATULATIONS!!\n\nWINNER: {winner}\nPRICE: {contract_price}\n")
```
ここで、仮に同額ベットした人が複数人いた場合、どうなるか考えてみた。最初に最大額をかけた人しかヒットしなくなるので、このプログラムは不十分だと言える。そこで下記のように改良してみた。

```python:auction2.py
#finishまではaction1.pyと同じなので割愛

contract_price = max(bids.values())       #最大額を落札価格と設定
winner = [max(bids,key=bids.get)]         #winnerをリスト化する
if price == contract_price:               #仮にbids[name](=price)が落札価格と同額だった場合
  winner.append(name)                     #リストwinnerに同額ビッターも格納する

print(f"CONGRATULATIONS!!\n\nWINNER: {','.join(winner)}\nPRICE: {contract_price}\n")
#あとは表記の問題。この時点ではwinnerはリストなので['Sakura','Takeru']みたいになるのが嫌だったので、
#区切り文字つき文字列連結「','.join()」を用いて終了。
```

これで無事、解決！！