「見つかったら止める」をやりたいのに break を使わないとどう書くか。初心者でも読める形で、代表的な書き方と例題を並べて説明します。
全体の考え方
- 目的: 条件が満たされたら、それ以上の処理を回さないこと。
- 基本戦略: ループ条件に「見つかったかどうか」を組み込む、または関数ごと終了する。
- 選び方: 小さなスクリプトならフラグで十分、再利用したいなら関数の return が最も読みやすい。
パターン1: フラグ変数+while 条件で止める
ループを「見つかっていない間だけ」回すように設計します。外側・内側の両方を自然に止められます。
# 例題: リストから最初の3の倍数を探す(break なし)
numbers = [5, 7, 10, 12, 20]
found = False
i = 0
value = None
while i < len(numbers) and not found:
if numbers[i] % 3 == 0:
value = numbers[i]
found = True
i += 1
print(value if found else "3の倍数は見つかりませんでした")
Python- ポイント: while の条件に not found を入れると、「見つかったら回さない」が明快。
- メリット: 入れ子ループでも、両方の while が止まる。
- 注意: インデックス操作が必要なので、for よりコードが増える。
パターン2: フラグ変数+for で最後に判定
for を使いつつ break は避けたい場合、ループ中は「見つけても覚えておく」だけにして、終了後に結果をまとめます。
# 例題: リストから最初の偶数を探す(break なし)
numbers = [3, 7, 11, 18, 21]
found = False
value = None
for n in numbers:
if not found and n % 2 == 0: # すでに見つけていたら何もしない
value = n
found = True
print(value if found else "偶数は見つかりませんでした")
Python- ポイント: 1回目だけ拾い、それ以降はスルーする条件にする。
- メリット: for の読みやすさを保ったまま、break を使わずに早期検出。
- 注意: ネストしたループでは外側まで止められない。フラグを外側の条件に使うか、関数化へ。
パターン3: 関数化して return で早期終了
「見つかったら処理全体をやめたい」なら、関数化して return を使うのが最もシンプルで読みやすい方法です。
# 例題: リストから最初の負の数を返す(break なし)
def find_first_negative(numbers):
for n in numbers:
if n < 0:
return n # 見つかったら関数ごと終了
return None # 見つからなかった場合
result = find_first_negative([5, 3, -2, 7, -8])
print(result if result is not None else "負の数は見つかりませんでした")
Python- ポイント: 「結論が出たら関数を終わる」意図が明確。
- メリット: 再利用・テストがしやすい。入れ子ループでも関数単位で止められる。
- 注意: スクリプト直書きだと return は使えないので、関数に切り出す。
パターン4: ジェネレータ式+next で最初だけ取得
「最初に一致したものだけ欲しい」ケースに強い、Python らしい書き方です。短くて意図が伝わります。
# 例題: リストから最初のゼロを探す(break なし)
numbers = [5, 3, 0, 7, 0]
first_zero = next((n for n in numbers if n == 0), None)
print(first_zero if first_zero is not None else "ゼロは見つかりませんでした")
Python- ポイント: next(generator, default) は「最初の一致」だけ取り出す定番。
- メリット: 自動で早期打ち切りされ、コードが非常に短い。
- 注意: ジェネレータ式に慣れていないと読みにくく感じることがある。
パターン5: 入れ子ループを while+フラグで止める
二重ループ以上では、break なしで外側まで止めるには「ループ条件にフラグ」を入れるのが分かりやすいです。
# 例題: 2次元リストから最初の文字列を探す(break なしで外側も止める)
grid = [
[10, 3.14, True],
["hello", 42, None],
["world", 0, False],
]
found = False
value = None
i = 0
while i < len(grid) and not found:
j = 0
while j < len(grid[i]) and not found:
x = grid[i][j]
if isinstance(x, str):
value = x
found = True
j += 1
i += 1
print(value if found else "文字列は見つかりませんでした")
Python- ポイント: どのループも「見つかっていない間だけ回す」ようにする。
- メリット: break なしで、処理全体の早期終了を実現。
- 注意: インデックスと状態の管理が増えるため、丁寧に書く。
どれを選ぶかの指針
- 小さなスクリプトなら: フラグ+while か、フラグ+for(終了後に判定)が手軽。
- 再利用したいなら: 関数+return が第一候補。入れ子でも自然に止められる。
- 短く書きたいなら: ジェネレータ+next。最初の一致を取る意図が明快。
- ネストが深いなら: while の条件にフラグを入れるか、関数に切り出して return。
よくある落とし穴と対策
- インデックス更新忘れ:
- 対策: while の末尾で必ず i や j を進める。進め忘れは無限ループの原因。
- フラグの初期化漏れ:
- 対策: found は必ず False で開始。見つかった値を保持する変数も初期化しておく。
- 読みづらい条件合成:
- 対策: while 条件が複雑なら、意味のある名前のフラグに分解する(例: not_found, in_range)。
練習問題(自分の手で動かして確認)
- 偶数の最初の値: フラグ+for と 関数+return の両方で実装して比較。
- None の検出: ジェネレータ+next で最初の None を取り、見つからない場合は “なし” を表示。
- 二重ループ: 2次元リストから最初の負の数を探し、while+フラグで外側まで止める。
「なぜ止めたいのか」を言葉にしてみると、break を使わずに止める設計が自然に選べるようになります。
