zipで組み合わせ

このレッスンで作るもの — 品名のリストと金額のリストを zip で組み合わせ、りんご 120円 の行に整える pair_lines を作ります。

zip で組み合わせる

ここまでは 1 本のリストを回してきました。ところが実際のおこづかい帳では、品名と金額という 2 つの情報 が組になっています。

まだ辞書を習っていないので、いまは品名だけのリストと金額だけのリストに分かれている、という状況を考えます。

names = ["りんご", "みかん", "パン"] prices = [120, 80, 250]

りんご の値段は 120みかん80パン250 です。同じ位置どうしが対応している、という約束で並んでいます。

位置で対応させる並べ方は、ずれた瞬間に全部が狂います。だからこそ、ずれを持ち込まない書き方を選ぶ意味があります。

番号で取り出す書き方の弱点

素直に書くと、番号を使って両方から取り出すことになります。

for i in range(len(names)): print(names[i] + " " + str(prices[i]) + "円")

動きますが、i という番号がコードの主役になってしまいます。names[i]prices[i] の片方だけ書き間違えると、品名と金額の組がずれます。しかも prices のほうが短いと IndexError で落ちます。

zip の形

zip は、複数のリストから 同じ位置の要素をまとめて 1 組ずつ 出してくれます。

for name, price in zip(names, prices): print(name, price)

これは りんご 120みかん 80パン 250 と表示します。enumerate のときと同じく、for のうしろに名前を 2 つ並べて受け取ります。番号を表す変数が消え、やりたいことだけがコードに残りました。

zip は 3 本以上のリストも受け取れます。zip(names, prices, categories) と書けば、for name, price, category in ... の形で 3 つ組を取り出せます。

長さが違うときは短いほうに合わせる

zip は、渡されたリストのうち いちばん短いもの に合わせて止まります。

names = ["りんご", "みかん", "パン"] prices = [120, 80] for name, price in zip(names, prices): print(name, price)

出るのは りんご 120みかん 80 の 2 組だけです。パン には相手がいないので捨てられます。エラーにならずに黙って切り捨てるので、そこは知っておく必要があります。

diagram (will load when visible)

行をつないで返す

前のレッスンと同じ要領で、改行を行の手前に足しながら 1 本の文字列にします。

def pair_lines(names, prices): result = "" for name, price in zip(names, prices): if result != "": result = result + "\n" result = result + name + " " + str(price) + "円" return result

pair_lines(["りんご", "みかん"], [120, 80]) の結果は "りんご 120円\nみかん 80円" です。第 1 章で決め打ちしていたレシートの中身が、外から渡した値で作れるようになりました。

第 1 章の make_receipt は 2 行を手で書いていました。いまは何件でも同じコードで組み立てられます。ループを覚えると、コードの長さと扱える件数が切り離せます。

よくある間違い

  1. zip に渡し忘れるfor name, price in names: と書くと、品名 1 文字ずつを 2 つに分けようとして ValueError になります。組にするには zip が要ります。
  2. 金額を文字列に変え忘れるname + " " + priceTypeError です。str(price) を挟みます。
  3. 長さのずれに気づかないzip は短いほうで止まり、余った分を黙って捨てます。件数が合うことを前提にするなら、len を比べて確かめる処理を別途書きます。

どちらかが空のリストなら 1 組も出ないので、result は空文字のまま返ります。

やってみよう

関数 pair_lines を実装してください。引数は 2 つで、names は品名 (str) のリスト、prices は金額 (int) のリストです。

zip で同じ位置どうしを組にし、"りんご 120円" の形に整えた行を改行 \n でつないだ 1 本の文字列を return します。品名と金額のあいだは半角スペース 1 つ、金額のうしろは全角の です。末尾に改行は付けません。

長さが違うときは zip の性質どおり、短いほうに合わせて切り上げます。どちらも空のときは空文字 "" を返します。

要件

  1. 関数名は pair_lines で、引数は names と prices の2つにする
  2. zip を使って同じ位置の品名と金額を組にして取り出す
  3. 各行は "りんご 120円" のように品名、半角スペース1つ、金額、全角の円 の順にする
  4. 行の区切りは \n を使い、末尾には改行を付けない

入出力例

pair_lines(["りんご","みかん","パン"], [120,80,250]) → "りんご 120みかん 80パン 250円" pair_lines(["りんご"], [120])"りんご 120円" pair_lines(["りんご","みかん","パン"], [120,80]) → "りんご 120みかん 80円" pair_lines(["りんご"], [120,80,250])"りんご 120円" pair_lines(["おまけ","パン"], [0,250]) → "おまけ 0パン 250円" pair_lines([], [])""

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.py
main.py
学習モード

メモ

zipで組み合わせ

⌘S で保存