setで重複除去
not in で毎回、全部を調べ直している
支出が 30 件あっても、使ったカテゴリは数種類です。「今月はどれを使ったか」を出したいとき、素直に書くとこうなります。
Python
seen = []
for name in names:
if name not in seen:
seen.append(name)動きはします。ただし 1 件ごとに、それまでに入れた全部と照らし合わせています。件数が増えるほど遅くなります。
「同じものを 2 つ持たない」という性質を最初から備えた入れ物が set です。日本語では集合と呼びます。リストを渡すだけで重複が消えます。
Python
names = ["パン", "牛乳", "パン", "パン"]
print(set(names)){'パン', '牛乳'} のような形で出ます。パン が 3 つあっても 1 つにまとまります。波かっこで囲まれますが辞書とは別もので、集合が持つのは値だけです。空の集合を作るときだけ注意が必要で、{} は空の 辞書 になります。空集合は set() と書きます。
空の集合から 1 つずつ足していくこともできます。そのときのメソッドは append ではなく add です。同じ値を 2 回足しても増えず、エラーにもならず静かに無視されます。この「入れても増えないことがある」という性質が、重複除去そのものです。
同じ入力なのに、並びが毎回違って見える
集合には決定的な弱点があります。順番を持たない ことです。リストは入れた順を守りますが、集合は守りません。
そのまま返してしまうと、同じ入力から同じ表示が得られる保証がなくなります。人に見せるにも、結果を比べるにも使えません。
対処は決まっていて、sorted を通します。sorted は集合を受け取っても動き、並びの決まったリスト を返します。
Python
print(sorted({"パン", "牛乳", "たまご"}))['たまご', 'パン', '牛乳'] が出ます。日本語の文字列は文字コードの順に並ぶので意味の順ではありませんが、何度実行しても同じ並びになります。ここが大事なところです。
「重複を消すときは集合、人に見せたり比べたりするときは sorted でリストに戻す」。この 2 段構えを型として覚えると迷いません。
集合には番号もありません。categories[0] のような取り出し方は TypeError になります。番号で取り出したいなら、先にリストへ変換します。
やってみよう
関数 used_categories(records) を実装してください。支出の辞書が並んだリストから category を集め、重複を除いた 並び順の決まったリスト を return します。
重複を消したあと、必ず sorted でリストにしてから返してください。集合のまま返すと結果が安定しません。空リストを渡されたときは空リスト [] を返します。同じカテゴリが何件あっても、返るのは 1 つだけです。
要件
- 関数名は used_categories で、引数は records の1つ
- 各支出の category を集め、set で重複を取り除く
- sorted でリストに変換してから return する。集合のまま返さない
- 空リストのときは空リストを返す