Python | ネストしたループで break を使う例

Python Python
スポンサーリンク

ネスト(入れ子)したループでは、「どのループを抜けるのか」をはっきり示すことが大切です。初心者がつまずきやすいポイントを避けつつ、使いどころ・避けどころ・代替手段を具体例で解説します。読み手が迷わないように、目的をコードで明確に表しましょう。


基本の考え方(どのループを抜ける?)

  • ポイント: break は「いま書いているループ(いちばん内側)」だけを抜けます。外側のループは続行されます。
  • 落とし穴: 「外側のループまで抜けたい」つもりで break を使っても、内側しか止まりません。
  • 指針: 目的が「内側だけ止める」のか「ループ全体を止める」のかを最初に決める。後者ならフラグや return を検討。

例題1: 行の中で最初の条件が見つかったら、その行の探索だけを終える

「各行の中で最初に偶数が見つかったら、その行は探索終了して次の行へ進む」例です。内側のループだけ break するのが自然です。

grid = [
    [3, 5, 8, 11],
    [7, 9, 13],
    [2, 4, 6]
]

for row in grid:
    for x in row:
        if x % 2 == 0:
            print("この行の最初の偶数:", x, "(行:", row, ")")
            break  # 内側(rowを走査中のループ)だけ抜ける
Python
  • ねらい: 行ごとに「最初の偶数だけ知りたい」なら、内側の break が最短で明快。
  • 効果: 各行の偶数が見つかった瞬間に無駄な探索をやめ、次の行へ進める。

例題2: グリッド中で条件が見つかったら「全体の探索を終了」する

「最初に偶数を一つでも見つけたら、もう全体をやめたい」なら、内側の break だけでは不十分。フラグや関数化+return を使うと読みやすくなります。

方法A: フラグ変数で外側も止める

found = False

for i, row in enumerate(grid):
    for j, x in enumerate(row):
        if x % 2 == 0:
            print("最初に見つけた偶数:", x, "(位置: 行", i, "列", j, ")")
            found = True
            break  # 内側を抜ける
    if found:
        break  # 外側も抜ける
Python
  • メリット: どのループを止めるかがコードの位置で理解できる。
  • デメリット: フラグの導入で少し冗長だが、意図は明確。

方法B: 関数にして return で「処理全体」を終了

def find_first_even(grid):
    for i, row in enumerate(grid):
        for j, x in enumerate(row):
            if x % 2 == 0:
                return (x, i, j)  # 関数ごと終了
    return None

result = find_first_even(grid)
if result:
    x, i, j = result
    print("最初の偶数:", x, "(位置: 行", i, "列", j, ")")
else:
    print("偶数は見つかりませんでした")
Python
  • メリット: 「見つかったら処理終わり」を最短・明快に表現できる。テストもしやすい。
  • デメリット: 関数化が前提。スクリプト直書きなら一手間増える。

例題3: 多段ネストで「どこを抜けるか」分かりづらい場合の整理

深いネストは読み手の負担が大きいので、分解して「役割ごとに止める」形にすると理解しやすくなります。

NG例(読みづらい)

for a in A:
    for b in B:
        for c in C:
            if is_target(a, b, c):
                break  # これは c ループだけを抜ける。意図が曖昧
        # ここで何が起きてほしい?さらに外側も止めたい?
Python

改善例(関数で責務を分ける)

def find_in_C(a, b, C):
    for c in C:
        if is_target(a, b, c):
            return c  # c探索の責務はここで終わり
    return None

found = None
for a in A:
    for b in B:
        c = find_in_C(a, b, C)
        if c is not None:
            found = (a, b, c)
            break  # bループを止める
    if found:
        break  # aループも止める

print("結果:", found)
Python
  • 効果: 「どの段で終わるか」を段階的に可視化でき、意図が伝わる。
  • 指針: 深いネストは関数分割+早期 return が有力。

例題4: 1行の中で複数条件のチェックと早期打ち切り(ガード的 break)

「一つでも不正が見つかったら、その行の検証は打ち切る」ようなバリデーションは、内側 break が適しています。

rows = [
    {"id": 1, "age": 20, "score": 80},
    {"id": 2, "age": -5, "score": 70},   # 不正
    {"id": 3, "age": 30, "score": 50}
]

for row in rows:
    for field in ("age", "score"):
        value = row[field]
        if field == "age" and value < 0:
            print("行ID", row["id"], "で不正な年齢:", value)
            break  # この行の検証はここで打ち切って次の行へ
        if field == "score" and not (0 <= value <= 100):
            print("行ID", row["id"], "で不正なスコア:", value)
            break
Python
  • ねらい: 「この行はもうダメ」と分かった時点で余計なチェックをしない。
  • 注意: 多条件が増えたら、検証ロジックを関数化するとより明解。

使い分けの指針(まとめ)

  • 内側だけ止めたい: その場の break がシンプルで分かりやすい。
  • 全体の探索を止めたい: フラグ+外側で break、または関数化して return の方が意図が明確。
  • 深いネストで混乱しそう: 関数分割し、各段階で早期 return。読みやすさとテスト容易性が向上。
  • “どのループを抜けるか”が曖昧: コードの位置で明示するか、名前付き関数に分けて責務をはっきりさせる。

追加の練習課題

  • 課題: 2次元リストで「最初に現れる3の倍数」を見つけ、見つかったら全体の探索を終了して位置を出力。
  • ヒント: フラグ方式と関数方式の両方で解いてみて、可読性の違いを比べる

模範解答

フラグ方式(外側ループも止める)

grid = [
    [2, 5, 7],
    [4, 9, 11],
    [8, 13, 15]
]

found = False

for i, row in enumerate(grid):
    for j, val in enumerate(row):
        if val % 3 == 0:  # 3の倍数を判定
            print("最初に見つけた3の倍数:", val, "(位置: 行", i, "列", j, ")")
            found = True
            break  # 内側ループを抜ける
    if found:
        break  # 外側ループも抜ける

if not found:
    print("3の倍数は見つかりませんでした")
Python

実行結果例

最初に見つけた3の倍数: 9 (位置: 行 1 列 1 )

関数方式(returnで処理全体を終了)

def find_first_multiple_of_three(grid):
    for i, row in enumerate(grid):
        for j, val in enumerate(row):
            if val % 3 == 0:
                return (val, i, j)  # 見つかったら関数ごと終了
    return None  # 見つからなかった場合

grid = [
    [2, 5, 7],
    [4, 9, 11],
    [8, 13, 15]
]

result = find_first_multiple_of_three(grid)

if result:
    val, i, j = result
    print("最初に見つけた3の倍数:", val, "(位置: 行", i, "列", j, ")")
else:
    print("3の倍数は見つかりませんでした")
Python

実行結果例

最初に見つけた3の倍数: 9 (位置: 行 1 列 1 )

まとめ

  • フラグ方式: ループを外側まで止めたいときに便利。処理の流れが見える。
  • 関数方式: 「見つかったら処理全体を終了」という意図を最短で表現できる。テストや再利用にも向いている。

👉 初心者はまず フラグ方式で「どのループを抜けるか」を理解し、慣れてきたら 関数方式でよりシンプルに書けるようになると良いです。

Python
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました