numbers = [3, 5, 4, 2, 1]
numbers.index{|val| val % 2 == 0} #=> 2
配列の要素を先頭から見ていき、条件に一致する最初の要素の位置がほしいということがよくあります。例として整数が格納された配列のうち、偶数となる最初の要素の位置を求めることを考えましょう。Rubyだと上記のようなワンライナーにより求めることができますが、Pythonではどのように書くべきでしょうか?
numbers = [3, 5, 4, 2, 1]
min((i for i in range(len(numbers)) if numbers[i] % 2 == 0), default=-1) #=> 2
与えられた条件を満たす要素のうち、添え字が最も小さいものを返すイメージですね。なお組み込み関数min
は与えられたイテレータが空のとき、例外を投げます。上記の例でいえば配列numbers
の中に偶数がない場合、i for i in range(len(numbers)) if numbers[i] % 2 == 0
が空になり、例外扱いとなります。ただしキーワード引数default
を指定すると、イテーレタが空でも例外にはならず、代わりにdefault
に指定した値を返します。要するにnumbers
に偶数が存在する場合は最初の偶数の要素の位置、存在しない場合は-1
を返すわけです。
ちなみに内包記法を使わないとなると次のようになりますが、Pythonらしいかどうかといわれると首をひねらざるを得ない見た目になってしまいます。そもそも可読性が高いとも思いません。またPythonの無名関数は特有の癖があるため、あまり使いたくないというのが本音だったりします。
numbers = [3, 5, 4, 2, 1]
min(filter(lambda i : numbers[i] % 2 == 0, range(len(numbers))), default=-1) #=> 2
余談: 最初にあげたRubyの例ですが、次のように書くこともできます。
numbers = [3, 5, 4, 2, 1]
numbers.index(&:even?) #=> 2