ここでは,辞書のキーについて完全一致や部分一致の検索,正規表現を使った検索を行う方法について説明します.まず,検索したい辞書を次のとおり作成します.
# 辞書の作成
members = {"加藤太郎": "かとうたろう", "佐藤次郎": "さとうじろう", "藤田太郎": "ふじたたろう", "武藤太": "むとうふとし", "藤": "ふじ"}
print(members)
{'加藤太郎': 'かとうたろう', '佐藤次郎': 'さとうじろう', '藤田太郎': 'ふじたたろう', '武藤太': 'むとうふとし', '藤': 'ふじ'}
このような辞書について,「加藤太郎」のようにキーに関する完全一致検索,「太郎」が含まれる条件で検索するという部分一致検索,さらに「藤」で始まるキーや「太」で終わるというような正規表現を使った検索を行います.
まず,「加藤太郎」に一致するキーを検索してその値を取得します.これは既にここで説明していますが,次のコードで取得できます.
# 完全一致の検索
print(members.get('加藤太郎'))
かとうたろう
キーと値をペアで(具体的にはタプル形式で)取得したい場合は次のコードが利用できます.
key = '加藤太郎'
result = (key, members.get(key))
print(result)
('加藤太郎', 'かとうたろう')
なお,get() は完全一致ですので,「加藤」では検索できません.
# これでは部分一致ができない
print(members.get('加藤'))
None
次は「加藤」「太郎」「太」などがキーに含まれる要素を検索しましょう.これは部分一致検索と呼ばれます.次のとおり,内包表記を利用した関数 search_members() を定義します.
def search_members(members, query):
return [name for name in members.keys() if query in name]
実際に検索を行います.部分一致検索が正しくできていることを確認してください.
print(search_members(members, "加藤")) # 「加藤」が含まれる
print(search_members(members, "太郎")) # 「太郎」が含まれる
print(search_members(members, "太")) # 「太」が含まれる
['加藤太郎'] ['加藤太郎', '藤田太郎'] ['加藤太郎', '藤田太郎', '武藤太']
次に,名前を部分一致で検索した上で値も同時に取得する関数を作成し,それを呼び出します.
def search_members_with_values(members: dict, query: str):
return [(name, members[name]) for name in members if query in name]
print(search_members_with_values(members, "加藤"))
print(search_members_with_values(members, "太郎"))
print(search_members_with_values(members, "太"))
[('加藤太郎', 'かとうたろう')]
[('加藤太郎', 'かとうたろう'), ('藤田太郎', 'ふじたたろう')]
[('加藤太郎', 'かとうたろう'), ('藤田太郎', 'ふじたたろう'), ('武藤太', 'むとうふとし')]
より複雑な検索を行いたい場合は「正規表現」を利用すると良いでしょう.正規表現を利用するためにはまずプログラムの先頭で re をインポートします.
import re
次の関数 search_members_regex() は正規表現を利用した検索が可能です.
def search_members_regex(members, pattern):
rx = re.compile(pattern)
return [name for name in members if rx.search(name)]
実際にその関数を呼び出して検索を行います.キーワードだけを指定した場合は部分一致検索が可能で,「^」や「$」による正規表現を用いた検索も可能です.具体的には「^」は「行頭」を意味するので,「^藤」では「藤」で始まるキーを検索できます.また「$」は行末を意味するので「太$」は「太」で終わるキーを検索できます.
print(search_members_regex(members, "太郎")) # 「太郎」が含まれる
print(search_members_regex(members, "藤")) # 「藤」が含まれる
print(search_members_regex(members, "^藤")) # 「藤」で始まる
print(search_members_regex(members, "太")) # 「太」が含まれる
print(search_members_regex(members, "太$")) # 「太」で終わる
['加藤太郎', '藤田太郎'] ['加藤太郎', '佐藤次郎', '藤田太郎', '武藤太', '藤'] ['藤田太郎', '藤'] ['加藤太郎', '藤田太郎', '武藤太'] ['武藤太']
次の関数 search_members_regex_with_values() ではキーだけでなくその値も取得可能です.
def search_members_regex_with_values(members, pattern):
rx = re.compile(pattern)
return [(name, members[name]) for name in members if rx.search(name)]
print(search_members_regex_with_values(members, "太郎")) # 「太郎」が含まれる
print(search_members_regex_with_values(members, "藤")) # 「藤」が含まれる
print(search_members_regex_with_values(members, "^藤")) # 「藤」で始まる
print(search_members_regex_with_values(members, "太")) # 「太」が含まれる
print(search_members_regex_with_values(members, "太$")) # 「太」で終わる
[('加藤太郎', 'かとうたろう'), ('藤田太郎', 'ふじたたろう')]
[('加藤太郎', 'かとうたろう'), ('佐藤次郎', 'さとうじろう'), ('藤田太郎', 'ふじたたろう'), ('武藤太', 'むとうふとし'), ('藤', 'ふじ')]
[('藤田太郎', 'ふじたたろう'), ('藤', 'ふじ')]
[('加藤太郎', 'かとうたろう'), ('藤田太郎', 'ふじたたろう'), ('武藤太', 'むとうふとし')]
[('武藤太', 'むとうふとし')]
同じような方法でリストなどからも部分一致や正規表現を利用した検索は可能です.一方で,ここで定義した関数はいずれも内包表記を利用した繰り返しの構文が利用されていることから,いわゆる総当たりの検索になります.このため数百件程度の辞書であれば総当たりでも十分速いですが,数万件以上になるような辞書を扱う場合は検索のパフォーマンスについて検討する必要が出てくることでしょう.データの件数が増えて速度が気になるときには n-gram などを使ったインデックス化を検討すると良いでしょう.