Pythonでループ処理をしている際に、最初や最後を判定する方法についてまとめました。
まず最初についての判定です。
range関数を繰り返す場合を考えてみます。
for i in range(5):
if i == 0:
print(f'最初:{i}')
else:
print(f'途中:{i}')
>>>
最初:0
途中:1
途中:2
途中:3
途中:4
これは動作しますが、ちょっとカッコ悪いです。
例えばrange関数を繰り返すのではなくて、普通のリストを繰り返すにはどうなるでしょうか?
my_list = ['first', 'second', 'third']
for i, val in enumerate(my_list):
if i == 0:
print(f'最初:{val}')
else:
print(f'途中:{val}')
>>>
最初:first
途中:second
途中:third
普通のリストを繰り返す場合にわざわざenumurate
関数を呼ぶことになってしまいました。
なので、以下のように変数を作った方が直感的でわかりやすいです。
my_list = ['first', 'second', 'third']
first = True
for val in my_list:
if first:
print(f'最初:{val}')
first = False
else:
print(f'途中:{val}')
>>>
最初:first
途中:second
途中:third
最後の判定は少し難しいです。
range関数では以下のような形でしょうか。
last_count = 5
for i in range(last_count):
if i == last_count - 1:
print(f'最後:{i}')
else:
print(f'途中:{i}')
>>>
途中:0
途中:1
途中:2
途中:3
最後:4
普通のリストではやはりenumurate
関数を使う形になると思います。
my_list = ['first', 'second', 'third']
for i, val in enumerate(my_list):
if i == len(my_list) - 1:
print(f'最後:{val}')
else:
print(f'途中:{val}')
>>>
途中:first
途中:second
最後:third
両方ともあまり直感的ではないです。
特にリストを繰り返す方については、enumurate(my_list,1)
という風にカウントを0以外で始まるように指定していたら、途端に意図しない結果になります。
my_list = ['first', 'second', 'third']
for i, val in enumerate(my_list, 1):
if i == len(my_list) - 1:
print(f'最後:{val}')
else:
print(f'途中:{val}')
>>>
途中:first
最後:second
途中:third
処理の最後の判定については、色々と議論がされており、代表的なものを紹介します。
def lookahead(iterable):
it = iter(iterable)
# ループを一個進めておいて、lastに最初の値を代入
last = next(it)
# secondとthirdを取り出す
for val in it:
yield last, True
# lastに代入
last = val
# 最後にyield
yield last, False
my_list = ['first', 'second', 'third']
for i, has_more in lookahead(my_list):
if has_more:
print(f'途中:{i}')
else:
print(f'最後:{i}')
>>>
途中:first
途中:second
最後:third
汎用的に使えそうですが、関数を別に設けるのが難点でしょうか。
事前に最後の要素だけを残してスライスを行い繰り返します。
繰り返しが終わった後に、最後の要素にのみ処理を施す形です。
for val in my_list[:-1]:
print(f'途中:{val}')
print(f'最後:{my_list[-1]}')
>>>
途中:first
途中:second
最後:third
こちらは短くてわかりやすいですね。
listの値がなくなるまでpop
関数で順番に取り出す方法です。
while my_list:
val = my_list.pop(0)
if my_list:
print(f'途中:{val}')
else:
print(f'最後:{val}')
>>>
途中:first
途中:second
最後:third
ただし、取り出した後はmy_list
の値が空になるので、注意が必要です。
print(my_list)
>>>
[]