Вы могли бы просто использовать бинарный поиск:
def binary_f(f,list):
frm = 0
to = len(list)
while frm < to:
mid = (frm+to)>>1
if f(list[mid]):
to = mid
else:
frm = mid+1
return frm
Это вернет первый индекс i
, для которых bool(f(list[i]))
является True
.
Конечно функция предполагает, что карта f
на list
имеет вид:
f(list) == [False,False,...,False,True,True,...,True]
Если это не так, то это, как правило, найти своп но один довольно не определено.
Say f
просто "версия 2 или выше" так lambda v:v >= '2'
, то он возвращает:
>>> binary_f(lambda v:v >= '2',['1.0', '1.14', '2.3', '3.1', '4'])
2
Так индекс 2
. В случае, если весь список вернется с объектами False
, он будет ** возвращать len(list)
. Так как «предполагает» элемент только за пределами списка будет оцениваться в True
:
>>> binary_f(lambda v:v >= '4.2',['1.0', '1.14', '2.3', '3.1', '4'])
5
Конечно, в вашем примере f
является works
.
Эксперименты:
>>> binary_f(lambda v:v >= '2',['1.0', '1.14', '2.3', '3.1', '4'])
2
>>> binary_f(lambda v:v >= '0',['1.0', '1.14', '2.3', '3.1', '4'])
0
>>> binary_f(lambda v:v >= '1',['1.0', '1.14', '2.3', '3.1', '4'])
0
>>> binary_f(lambda v:v >= '1.13',['1.0', '1.14', '2.3', '3.1', '4'])
1
>>> binary_f(lambda v:v >= '2.4',['1.0', '1.14', '2.3', '3.1', '4'])
3
>>> binary_f(lambda v:v >= '3',['1.0', '1.14', '2.3', '3.1', '4'])
3
>>> binary_f(lambda v:v >= '3.2',['1.0', '1.14', '2.3', '3.1', '4'])
4
>>> binary_f(lambda v:v >= '4.2',['1.0', '1.14', '2.3', '3.1', '4'])
5
(я здесь, конечно, сделал очень дешевую проверку версии, но это работает, конечно, для более сложных предикатов).
Поскольку это бинарный поиск, он будет работать в O (журнал N) с п число элементов в списке, тогда как линейный поиск может результат O (N) проверок (который обычно дороже).
EDIT: в случае, если список содержит два значения, и вы хотите, чтобы найти своп, вы можете просто первым вычислить значение индекса 0
:
val0 = f(list[0])
, а затем обеспечить binary_f
:
binary_f(lambda v:works(v) != val0,list)
Или положить его в отличную функцию:
def binary_f_val(f,list):
val0 = f(list[0])
return binary_f(lambda x:f(x) != val0,list)
Почему этот вопрос ниспровергнут? –