1
3

Pythonの便利技と注意点:辞書編

Last updated at Posted at 2024-04-13

目次に戻る

strが入ってる辞書を打鍵数を少なくして作成する方法

キーはstrを''で囲まなくても辞書を作成してくれる
menu = dict(ハンバーガー='焼く', ポテト='揚げる')
print(menu)
==================================================
# 実行結果
{'ハンバーガー': '焼く', 'ポテト': '揚げる'}
値は''で囲まないとエラーになる
menu = dict(ハンバーガー=焼く, ポテト=揚げる)
print(menu)
===============================================
# 実行結果
    menu = dict(ハンバーガー=焼く, ポテト=揚げる)
                       ^^
NameError: name '焼く' is not defined

items()でkeyとvalue両方をとってくる

lunch_menu = {
    'Mon': 'Hamburger',
    'Tue': 'Curry',
    'Wed': 'Sushi',
    'Thu': 'Ramen',
    'Fri': 'Beef steak'
}

for week_day, menu in lunch_menu.items():
    print(week_day, ':', menu)
出力結果
Mon : Hamburger
Tue : Curry
Wed : Sushi
Thu : Ramen
Fri : Beef steak

辞書のcopy()とdeepcopy()

copyは新しい値を返す為、copy先の値を変えても、copy元は変えない
>>> dicA = {'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}
>>> dicB = dicA.copy()
>>> dicB
{'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}

>>> dicB['名前'] = '次郎'
>>> dicB
{'名前': '次郎', '備品': ['PC', '携帯', 'カバン']}
>>> dicA
{'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}
値がオブジェクトの場合は、copy元を参照する為、copy先を変えるとcopy元も変わる
>>> dicA = {'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}
>>> dicB = dicA.copy()

>>> dicB['備品'].remove('携帯')

>>> dicB
{'名前': '太郎', '備品': ['PC', 'カバン']}
>>> dicA
{'名前': '太郎', '備品': ['PC', 'カバン']}
deepcopy()を使うと、オブジェクトも全て新しい値を作り出す為、copy先のオブジェクト変更がcopy元に影響しない
>>> from copy import deepcopy
>>> dicA = {'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}
>>> dicC = deepcopy(dicA)

>>> dicC['名前'] = '三郎'
>>> dicC
{'名前': '三郎', '備品': ['PC', '携帯', 'カバン']}
>>> dicA
{'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}

>>> dicC['備品'].remove('携帯')
>>> dicC
{'名前': '三郎', '備品': ['PC', 'カバン']}
>>> dicA
{'名前': '太郎', '備品': ['PC', '携帯', 'カバン']}

辞書入りプログラムで存在しない項目にアクセスした時にpythonエラーではなくNoneを返してくれるget()

辞書にない項目にアクセスすると通常エラーが返る
>>> dicZ = {}
>>> print(dicZ['name'])
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    print(dicZ['name'])
KeyError: 'name'
get()を使うことで項目がないとNoneと返してくれる
>>> dicZ = {}
>>> print(dicZ.get('name'))
None
第二引数にデフォルト値を設定することで、その値を表示することも可能
>>> dicZ = {}
>>> dicZ.get('name', 'ありません')
'ありません'

リストにあるkeyに対応する値を辞書からとってくる

辞書.get(key)
>>> dic = {'A': 1, 'B':2, 'C':3, 'D':4}
>>> key_list = ['B', 'C', 'D', 'A']
>>> for key in key_list:
...     print(key, ':', dic.get(key))
... 
B : 2
C : 3
D : 4
A : 1

各文字がいくつあるのか数えて辞書形式で出力する

新たな文字が出てきた時に0をセットしてfor文で回す方法
>>> strs = "jjjssssaawoa;slblskwpalswa;cbx"
>>> d = {}
>>> for c in strs:
...     if c not in d:
...             d[c] = 0
...     d[c] += 1
... 
>>> print(d)
{'j': 3, 's': 7, 'a': 5, 'w': 3, 'o': 1, ';': 2, 'l': 3, 'b': 2, 'k': 1, 'p': 1,
 'c': 1, 'x': 1}
setdefault()関数を使う方法
>>> strs = "jjjssssaawoa;slblskwpalswa;cbx"
>>> d = {}
>>> for c in strs:
...     d.setdefault(c, 0)
...     d[c] += 1
... 
>>> print(d)
{'j': 3, 's': 7, 'a': 5, 'w': 3, 'o': 1, ';': 2, 'l': 3, 'b': 2, 'k': 1, 'p': 1,
 'c': 1, 'x': 1}

辞書のupdate()

既存のキーは更新、存在しないキーは追加となる
set_menu_order = {'ハンバーガー': 250, 'ポテトS': 150}
modified_set_menu_order = {'ハンバーガー': 300, 'コーラS': 100}

set_menu_order.update(modified_set_menu_order)
print(set_menu_order)
出力結果
{'ハンバーガー': 300, 'ポテトS': 150, 'コーラS': 100}

辞書形式でCSVファイルに出力する

# csvパッケージをインポート
import csv

# 列名設定
fieldnames = ['Menu', 'Price']

# ファイル書き込み開始
# ※1行ずつ空いてしまう場合、newline=''オプションをつける
with open('example.csv', 'w', newline='') as f:

    # csvパッケージのDictWriter()関数を呼び出し、ファイル名と列名を指定
    writer = csv.DictWriter(f, fieldnames)

    # 最初に列を書く
    writer.writeheader()

    # writerow()関数を使って、辞書形式で{'列名': '値'}を書き込む
    writer.writerow({'Menu': 'ハンバーガー', 'Price': 300})
    writer.writerow({'Menu': 'ポテト', 'Price': 150})
    writer.writerow({'Menu': 'ドリンク', 'Price': 100})
出力結果(example.csv)
Menu,Price
ハンバーガー,300
ポテト,150
ドリンク,100

CSVファイルを辞書形式で1行ずつ読み込む

DictReader()関数を使用する
# csvパッケージをimport
import csv

# CSVファイルを読みとりで開く
# ※1行ずつ空いてしまう場合、newline=''オプションをつける
with open('example.csv', 'r', newline='') as f:

    # csvパッケージのDictReader()関数を呼び出し、ファイル名を指定
    reader = csv.DictReader(f)

    # for文で辞書型で読み込んだファイルを1行ずつ変数に格納して
    # 変数['列名']と指定する
    for row in reader:
        print(row['Menu'], row['Price'])
出力結果(example.csv)
ハンバーガー 300
ポテト 150
ドリンク 100

CSVファイルを読み込んでデータを更新する技

csv.DictWriterで読み込んだものをアップデートする方法が見つからなかったため、下記手順を行った。

1.辞書型変数準備
2.CSVfileをcsv.DictReaderで1行ずつ読み込み、1.で準備した辞書型変数に追加
3.辞書型変数の中の値を更新
4.更新し終えたらwith open('CSVファイル名', 'w', newline='')でCSVファイルを上書きモードで開く
5.csv.DictWriter()関数を使ってCSVファイルを丸ごと上書きする

更新前のCSVファイル(example.csv)
Menu,Price
ハンバーガー,300
ポテト,150
ドリンク,100

例としてポテトを200円に更新する
# csvパッケージをimport
import csv

# 辞書型変数を準備
menu_dic = {}

# 列名設定
fieldnames = ['Menu', 'Price']

# CSVファイルを1行ずつ読み込んで、準備した辞書型変数に格納
with open('example.csv', 'r', newline='') as f:
    reader = csv.DictReader(f)
    for row in reader:
        menu_dic.update({row['Menu']: int(row['Price'])})

# 確認のため以下のコードを実行すると、下記のように出力される
# 
# 更新前辞書型変数
# {'ハンバーガー': 300, 'ポテト': 150, 'ドリンク': 100}

print('更新前辞書型変数')
print(menu_dic)

# 準備した辞書型変数内の「ポテト」の値段を更新
menu_dic['ポテト'] = int(200)

# 確認のため以下のコードを実行すると、下記のように出力される
# 
# 更新前辞書型変数
# {'ハンバーガー': 300, 'ポテト': 200, 'ドリンク': 100}
print('更新後辞書型変数')
print(menu_dic)

# CSVファイルを上書きモードで開く
with open('example.csv', 'w', newline='') as f:

    # csv.DictWriter()関数で列名までCSVファイルに出力
    writer = csv.DictWriter(f, fieldnames)
    writer.writeheader()

    # for文とitems()関数を使い、writerow関数を使って
    # 辞書型変数の中身を、辞書形式({'列名': 値})で
    # CSVファイルに出力する
    for menu, price in menu_dic.items():
        writer.writerow({'Menu': menu, 'Price': price})
更新後のCSVファイル(example.csv)
Menu,Price
ハンバーガー,300
ポテト,200
ドリンク,100

CSVファイルの内容をデータの並び順ではない順番で表示後、データを追加・更新した上でCSVファイルに反映させる技

例として、値段の高いメニューから順番に表示して、メニューを追加・更新したものをCSVファイルに反映させるとする。

CSVファイルが下記のようになっている場合、一番高いダブルバーガーから表示して、最後はハンバーガを表示する。
その後、ポテト200円を追加して、ダブルバーガーを450円に変更するとする。

更新前CSVファイル(example.csv)
Menu,Price
ハンバーガー,300
チーズバーガー,400
ダブルバーガー,500
てりやきバーガー,350

手順は下記の通り。
1.CSVファイルを読み込んでOriginal_Menu_Dicに格納
2.Original_Menu_Dicをコピーして表示用の辞書Display_Menu_Dicに複製
3.一番値段の高いデータを表示して、そのデータをDisplay_Menu_Dicから削除、を繰り返す
4.全て表示してDisplay_Menu_Dicのデータがなくなったら、Original_Menu_Dicにポテト200円を追加して、ダブルバーガー450円を更新する
5.更新されたOriginal_Menu_DicをCSVファイルに上書き保存

# deepcopy関数とcsvパッケージをimport
from copy import deepcopy
import csv


# 辞書型変数宣言
Original_Menu_Dic = {}
Display_Menu_Dic = {}

# 列名設定
fieldnames = ['Menu', 'Price']

# Original_Menu_Dic作成
with open('example.csv', 'r', newline='') as f:
    reader = csv.DictReader(f)
    for row in reader:
        Original_Menu_Dic.update({row['Menu']: int(row['Price'])})

# Display_Menu_Dic作成
Display_Menu_Dic = deepcopy(Original_Menu_Dic)

# 確認のため以下のコードを実行すると、下記のように出力される
#
# 更新前辞書型変数
# Original_Menu_Dic: {'ハンバーガー': 300, 'チーズバーガー': 400, 'ダブルバーガー': 500, 'てりやきバーガー': 350}
# Display_Menu_Dic: {'ハンバーガー': 300, 'チーズバーガー': 400, 'ダブルバーガー': 500, 'てりやきバーガー': 350}
print('更新前辞書型変数')
print('Original_Menu_Dic:', Original_Menu_Dic)
print('Display_Menu_Dic:', Display_Menu_Dic)
print('')

# メニューの中身を値段の高い順に表示
while len(Display_Menu_Dic) > 0:

    # 使用する変数を初期化
    # ※ループの度に初期化しないと前のループの段階で格納された値が残る
    tmp_menu = ''
    tmp_price = 0
    max_menu = ''
    max_price = 0

    # for文とitems()関数でメニューの中で一番高額なメニューを探しだす
    for tmp_menu, tmp_price in Display_Menu_Dic.items():

        # 一番高いメニューに何も入ってない(ループの一番最初)
        # あるいは
        # 読み込んだメニューの方が高額であれば
        # そのメニューを一番高額なメニューとして設定する
        if (max_menu == '') | (tmp_price > max_price):
            max_menu = tmp_menu
            max_price = tmp_price

    # 一番高額なメニューを表示して
    # 同じメニューを表示しないようにDisplay_Menu_Dicから削除する
    print('メニュー:', max_menu, '価格:', max_price)
    del Display_Menu_Dic[max_menu]

# 確認のため以下のコードを実行すると、下記のように出力される
# 表示用の辞書からはデータが全て消えているが
# 辞書データをdeepcopy()したため、元のメニューには影響がない
#
# メニュー表示後辞書型変数
# Original_Menu_Dic: {'ハンバーガー': 300, 'チーズバーガー': 400, 'ダブルバーガー': 500, 'てりやきバーガー': 350}
# Display_Menu_Dic: {}
print('')
print('メニュー表示後辞書型変数')
print('Original_Menu_Dic:', Original_Menu_Dic)
print('Display_Menu_Dic:', Display_Menu_Dic)
print('')

# ポテト200円を追加、ダブルバーガーの値段を450円に更新
Original_Menu_Dic['ポテト'] = int(200)
Original_Menu_Dic['ダブルバーガー'] = int(450)

# 確認のため以下のコードを実行すると、下記のように出力される
#
# メニュー更新後辞書型変数
# Original_Menu_Dic: {'ハンバーガー': 300, 'チーズバーガー': 400, 'ダブルバーガー': 450, 'てりやきバーガー': 350, 'ポテト': 200}
# Display_Menu_Dic: {}
print('メニュー更新後辞書型変数')
print('Original_Menu_Dic:', Original_Menu_Dic)
print('Display_Menu_Dic:', Display_Menu_Dic)
print('')

# 更新を終えたOriginal_Menu_Dicを
# csv.DictWriter()関数を使ってCSVファイルに上書きする
with open('example.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames)
    writer.writeheader()

    for menu, price in Original_Menu_Dic.items():
        writer.writerow({'Menu': menu, 'Price': price})
出力結果
メニュー: ダブルバーガー 価格: 500
メニュー: チーズバーガー 価格: 400
メニュー: てりやきバーガー 価格: 350
メニュー: ハンバーガー 価格: 300
更新後CSVファイル(example.csv)
Menu,Price
ハンバーガー,300
チーズバーガー,400
ダブルバーガー,450
てりやきバーガー,350
ポテト,200

目次に戻る

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3