リストの繰り返し:for文でリストを処理する#

はじめに#

前回までに、Pythonのリストの基本、要素の追加・削除、スライスによる部分リストの取り出し方について学びました。今回は、リストの中の要素を一つずつ処理する「繰り返し処理」について学んでいきます。

リストの各要素に対して同じ処理を行いたい場合#

例えば、商品リストがあって、すべての商品の名前を画面に表示したい場合を考えてみましょう。これまでの学んだ知識をもとにすると、次のように書けそうです。

>
products = ["ノートパソコン", "スマートフォン", "タブレット", "ヘッドフォン", "スピーカー"]

# 各商品を表示
for i in range(len(products)):
    print(products[i])
ノートパソコン
スマートフォン
タブレット
ヘッドフォン
スピーカー

これは、以前学んだ for ループと range() 関数、len() 関数を使って、リストの長さを調べて、その長さ分だけ繰り返し処理を行っています。リストのインデックス(位置)を使って、各要素にアクセスしています。

この方法でも問題ありませんが、Pythonではリストの要素を直接取り出すためのもっと簡単な書き方があります。

for文でリストを処理する#

Pythonでは、次のような書き方でリストの要素を一つずつ取り出して処理できます。

>
products = ["ノートパソコン", "スマートフォン", "タブレット", "ヘッドフォン", "スピーカー"]

# 各商品を表示
for product in products:
    print(product)
ノートパソコン
スマートフォン
タブレット
ヘッドフォン
スピーカー

この例では、for product in products: というコードで、productsリストの各要素が、一つずつproduct変数に入れられて処理されます。リストの最初の要素から順番に処理され、最後の要素まで処理すると終了します。

この書き方は、リストの要素を直接取り出すので、インデックス(i)を必要とせず、また len()range() を使う必要もありません。そのため、よりシンプルで読みやすいコードになります。

リストの要素を詳細に分析する#

より複雑な例として、テストの点数リストから平均点、最高点、最低点を計算してみましょう。

>
scores = [85, 92, 78, 65, 98, 89, 75, 82]
total = 0
max_score = scores[0]  # 最初の値で初期化
min_score = scores[0]  # 最初の値で初期化

# 点数を分析する
for score in scores:
    total += score  # 合計に加える

    if score > max_score:  # 最高点の更新
        max_score = score

    if score < min_score:  # 最低点の更新
        min_score = score

average = total / len(scores)  # 平均点を計算

print(f"テスト結果: {scores}")
print(f"平均点: {average:.1f}点")
print(f"最高点: {max_score}点")
print(f"最低点: {min_score}点")
テスト結果: [85, 92, 78, 65, 98, 89, 75, 82]
平均点: 83.0点
最高点: 98点
最低点: 65点

この例では、for文でリスト内の各点数を取り出し、以下の処理を行っています。

  1. 点数を合計に加える
  2. 現在の最高点より高ければ、最高点を更新
  3. 現在の最低点より低ければ、最低点を更新

リスト内の要素を順番に処理しながら、複数の情報を同時に集められるのがfor文の強みです。

リストのインデックス(位置)も知りたい場合#

リストの要素だけでなく、その位置(インデックス)も同時に知りたい場合は、enumerate() 関数を使います。

>
fruits = ["りんご", "バナナ", "オレンジ", "ぶどう", "メロン"]

# インデックスと要素を同時に取得
for index, fruit in enumerate(fruits):
    print(f"位置{index}: {fruit}")
位置0: りんご
位置1: バナナ
位置2: オレンジ
位置3: ぶどう
位置4: メロン

enumerate() は「インデックスと要素のペア」を返してくれる関数です。これを使うと、「何番目の要素か」という情報も利用できるようになります。上の例では、index 変数にインデックスが、fruit 変数に fruits の各要素が入ります。

複数のリストを同時に処理する(zip関数)#

複数のリストの対応する要素を同時に処理したい場合は、zip() 関数が便利です。zip()は、複数のリストの「対応する位置の要素」を組み合わせて処理できるようにする関数です。

forループとzipを使ったシンプルな例#

>
names = ["田中", "鈴木", "佐藤"]
ages = [25, 30, 22]

# forループでzipを使う
for name, age in zip(names, ages):
    print(f"{name}さんは{age}歳です")
田中さんは25歳です
鈴木さんは30歳です
佐藤さんは22歳です

zip()が「田中と25」「鈴木と30」「佐藤と22」のように、対応する位置の要素を組み合わせています。

zipの代わりにインデックスを使う方法との比較#

zip()を使わない場合は、インデックスで処理するとこうなります。

>
names = ["田中", "鈴木", "佐藤"]
ages = [25, 30, 22]
# インデックスを使ってリストを処理
for i in range(len(names)):
    print(f"{names[i]}さんは{ages[i]}歳です")

この方法でも同じ結果が得られますが、zip()を使った方がコードがシンプルで読みやすくなります。

3つ以上のリストを同時に処理する#

zip()は2つだけでなく、3つ以上のリストも同時に処理できます。

>
products = ["ノートパソコン", "スマートフォン", "タブレット", "ヘッドフォン", "スピーカー"]
prices = [80000, 60000, 45000, 15000, 8000]
stocks = [12, 25, 8, 15, 30]

# 3つのリストを一緒に処理
for product, price, stock in zip(products, prices, stocks):
    print(f"{product}: {price}円 (在庫: {stock}個)")
    if stock < 10:
        print("  ※在庫が少なくなっています")
ノートパソコン: 80000円 (在庫: 12個)
スマートフォン: 60000円 (在庫: 25個)
タブレット: 45000円 (在庫: 8個)
  ※在庫が少なくなっています
ヘッドフォン: 15000円 (在庫: 15個)
スピーカー: 8000円 (在庫: 30個)

ここでは3つのリスト(商品名、価格、在庫数)の対応する要素を同時に取り出しています。このように、関連する情報が別々のリストに保存されている場合、zip()を使うとシンプルに処理できます。

長さが異なるリストをzipで処理する場合#

異なる長さのリストをzip()で処理すると、最も短いリストの長さに合わせて処理されます。

>
list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c']

for num, char in zip(list1, list2):
    print(f"{num} - {char}")
1 - a
2 - b
3 - c

長い方のリスト(list1)の残りの要素(4と5)は無視されることに注意してください。

ネストしたリスト(リストの中のリスト)を処理する#

リストの中に別のリストが入っている「ネストしたリスト」も、for文で処理できます。例えば、複数の生徒の複数の科目の点数を管理する場合を考えてみましょう。

>
# 生徒ごとの点数 [国語, 数学, 英語, 理科, 社会]
student_scores = [
    [85, 90, 78, 92, 88],  # 生徒1
    [92, 85, 95, 78, 90],  # 生徒2
    [78, 65, 85, 75, 82]   # 生徒3
]

# 各生徒の平均点を計算
for i, scores in enumerate(student_scores):
    total = sum(scores)  # sum関数でリストの合計を計算
    average = total / len(scores)
    print(f"生徒{i}の点数: {scores}")
    print(f"生徒{i}の平均点: {average:.1f}")
    print("---")
生徒0の点数: [85, 90, 78, 92, 88]
生徒0の平均点: 86.6
---
生徒1の点数: [92, 85, 95, 78, 90]
生徒1の平均点: 88.0
---
生徒2の点数: [78, 65, 85, 75, 82]
生徒2の平均点: 77.0
---

この例では、student_scores はリストの中にリストが入った2次元の構造になっています。外側のfor文で生徒ごとのリストを取り出し、sum() 関数を使って各生徒の点数の合計を計算しています。

ネストしたリストの各要素にアクセスするには、2重のfor文を使うこともできます。

>
# 生徒ごとの点数 [国語, 数学, 英語, 理科, 社会]
student_scores = [
    [85, 90, 78, 92, 88],  # 生徒1
    [92, 85, 95, 78, 90],  # 生徒2
    [78, 65, 85, 75, 82]   # 生徒3
]

subjects = ["国語", "数学", "英語", "理科", "社会"]

# 各生徒、各科目の点数を表示
for i, scores in enumerate(student_scores):
    print(f"生徒{i}の科目別点数:")
    for j, score in enumerate(scores):
        print(f"  {subjects[j]}: {score}点")
    print("---")
生徒0の科目別点数:
  国語: 85点
  数学: 90点
  英語: 78点
  理科: 92点
  社会: 88点
---
生徒1の科目別点数:
  国語: 92点
  数学: 85点
  英語: 95点
  理科: 78点
  社会: 90点
---
生徒2の科目別点数:
  国語: 78点
  数学: 65点
  英語: 85点
  理科: 75点
  社会: 82点
---

このように、ネストしたリストでも、for文を適切に組み合わせることで、すべてのデータに順番にアクセスできます。

まとめ#

今回は、リストの繰り返し処理について学びました。

  • リストの各要素を順番に処理するにはfor文が便利
  • for item in list: の形で書くと、listの各要素がitemに入れられて処理される
  • for文とif文を組み合わせると、条件に合う要素だけを処理できる
  • enumerate() 関数を使うと、インデックス(位置)と要素を同時に取得できる
  • zip() 関数を使うと、複数のリストを同時に処理できる
  • ネストしたリスト(リストの中のリスト)は、複数のfor文を使って処理できる

for文を使いこなせると、リストを効率的に処理できるようになります。例えば、データの集計、フィルタリング、変換など、さまざまな処理が簡潔に書けるようになります。