zipで組み合わせ
番号でそろえると、片方だけずれる
ここまでは 1 本のリストを回してきました。ところが実際のおこづかい帳では、品名と金額という 2 つの情報が組になっています。まだ辞書を習っていないので、いまは 2 本のリストに分かれている状況を考えます。
Python
names = ["りんご", "みかん", "パン"]
categories = ["食費", "食費", "娯楽"]同じ位置どうしが対応している、という約束で並んでいます。素直に書くと、位置を表す番号を使って両方から取り出すことになります。
Python
for i in range(len(names)):
print(names[i] + " は " + categories[i])動きますが、i という番号がコードの主役になってしまいます。names[i] と categories[i] の片方だけ書き間違えると、組がずれます。しかも片方が短いと IndexError で落ちます。
同じ位置どうしを 1 組で取り出す
zip は、複数のリストから 同じ位置の要素をまとめて 1 組ずつ 出してくれます。
Python
for name, category in zip(names, categories):
print(name + " は " + category)enumerate のときと同じく、for のうしろに名前を 2 つ並べて受け取ります。番号を表す変数が消え、やりたいことだけがコードに残りました。3 本以上のリストも渡せて、その場合は受け取る名前も 3 つ並べます。
短いほうに黙って合わせる
zip は、渡されたリストのうち いちばん短いもの に合わせて止まります。
Python
names = ["りんご", "みかん", "パン"]
categories = ["食費", "食費"]
for name, category in zip(names, categories):
print(name, category)出るのは 2 組だけで、パン は相手がいないので捨てられます。エラーにならず黙って切り捨てるので、件数がずれていても気づけません。件数が合うことを前提にしたいなら、len を比べて確かめる処理を自分で書きます。
どちらかが空のリストなら 1 組も出ないので、入れ物は用意したときのまま残ります。
zipに渡し忘れてfor name, category in names:と書くと、1 件を 2 つに分けようとしてValueErrorになります。組にするにはzipが要ります。
やってみよう
関数 pair_lines(names, prices) を実装してください。引数は 2 つで、names は品名 (str) のリスト、prices は金額 (int) のリストです。
zip で同じ位置どうしを組にし、"りんご 120円" の形に整えた行を改行 \n でつないだ 1 本の文字列を return します。品名と金額のあいだは半角スペース 1 つ、金額のうしろは全角の 円 です。末尾に改行は付けません。
長さが違うときは zip の性質どおり、短いほうに合わせて切り上げます。どちらも空のときは空文字 "" を返します。区切りの入れ方は前回と同じ考え方です。
要件
- 関数名は pair_lines で、引数は names と prices の2つにする
- zip を使って同じ位置の品名と金額を組にして取り出す
- 各行は "りんご 120円" のように品名、半角スペース1つ、金額、全角の円 の順にする
- 行の区切りは \n を使い、末尾には改行を付けない