key
引数は、によってmin
最小値を決定するものを示します。
key
引数を指定しないmin
と、任意のタプル全体が他のタプルと比較され、タプル内の最初の要素が最初に比較されます。関数は入力シーケンスのkey
各要素に対して呼び出され、最小要素はそのキーの戻り値のみによって決定されます。lambda k: k[1]
タプルの 2 番目の要素を返します。
次の 2 つの結果を比較します。
>>> example = [(5, 1), (4, 2), (3, 3), (2, 4), (1, 5)]
>>> min(example)
(1, 5)
>>> min(example, key=lambda element: element[1])
(5, 1)
最初の例では、key
関数は提供されず、min()
各タプルをそのまま比較します。2 番目の例では、関数が返すmin()
ものだけを見て、異なる要素を最小値として選択します。key()
あなたはその主要な機能で本当に船外に出ることができます:
>>> min(example, key=lambda element: (element[0] / element[1]) + element[1])
(4, 2)
usingstr
は実際には必要なく、式全体が過度に冗長です。次のように単純化できます。
i = min((x for x in aList if x[2] == 1), key=lambda k: k[1])
または使用operator.itemgetter
:
from operater import itemgetter
i = min((x for x in aList if x[2] == 1), key=itemgetter(1))
itertools
隣接するペアを比較するには、ヘルパー関数が必要です:
from itertools import tee, izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
次に、次を使用して、「最後の要素が 1 である」基準をフィルターに移動する方が簡単ですitertools.ifilter
。
from itertools import ifilter
last_is_one = ifilter(lambda x: x[2] == 1, aList)
paired = pairwise(last_is_one)
これで、実際の作業を行うことができます。隣接するリストの各ペアについて、2 番目の要素の合計が最小のペアを見つけ、そのペアから 2 番目の要素ごとに最小のものを見つけます。
# find minimum pair by second elements summed
minpair = min(paired, key=lambda pair: pair[0][1] + pair[1][1])
minimum = min(minpair, key=itemgetter(1))
すべてをまとめると、フィルタリングの責任は関数の呼び出し元に委ねられます。
from operater import itemgetter
from itertools import tee, izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
def neighbouring_minimum(iterable):
paired = pairwise(iterable)
# find minimum pair by second elements summed
minpair = min(paired, key=lambda pair: pair[0][1] + pair[1][1])
return min(minpair, key=itemgetter(1))
サンプル入力の場合:
>>> from itertools import ifilter
>>> aList = [[10564, 15, 1], [10564, 13, 1], [10589, 18, 1], [10637, 39, 1], [10662, 38, 1], [10837, 45, 1], [3, 17, 13], [7, 21, 13], [46, 1, 13]]
>>> filtered = ifilter(lambda x: x[2] == 1, aList)
>>> neighbouring_minimum(filtered)
[10564, 13, 1]
最小値の基準を別のキー引数に移動することもできます:
def neighbouring_minimum(iterable, key=None):
if key is None:
# default to the element itself
key = lambda x: x
paired = pairwise(iterable)
# find minimum pair by key summed
minpair = min(paired, key=lambda pair: sum(map(key, pair)))
return min(minpair, key=key)
neighbouring_minimum(ifilter(lambda x: x[2] == 1, aList), key=itemgetter(1))