Заменить цикл в Python на эквивалент поиска в Matlab
Предположим, у меня есть отсортированный массив кортежей, который отсортирован по первому значению. Я хочу найти первый индекс, где выполняется условие для первого элемента кортежа. т.е. как мне заменить следующий код
test_array = [(1,2),(3,4),(5,6),(7,8),)(9,10)]
min_value = 5
index = 0
for c in test_array:
if c[0] > min_value:
break
else:
index = index + 1
С эквивалентом Matlab найти?
т.е. в конце этого цикла я ожидаю получить 3, но я бы хотел сделать это более эффективным. Я штраф с использованием NumPy для этого. Я пытался использовать argmax, но безрезультатно.
Спасибо
3 ответа
Поскольку список отсортирован, и если вы знаете максимально возможное значение для второго элемента (или если может быть только 1 элемент с таким же первым значением), вы можете применить bisect
в списке кортежей (возвращает отсортированную позицию вставки в списке)
import bisect
test_array = [(1,2),(3,4),(5,6),(7,8),(9,10)]
min_value = 5
print(bisect.bisect_left(test_array,(min_value,10000)))
Жесткое кодирование до 10000 плохо, поэтому, если у вас есть только целые числа, вы можете сделать это вместо этого:
print(bisect.bisect_left(test_array,(min_value+1,)))
результат: 3
если у вас есть числа с плавающей точкой (также работает с целыми числами), вы можете использовать sys.float_info.epsilon
как это:
print(bisect.bisect_left(test_array,(min_value*(1+sys.float_info.epsilon),)))
Она имеет O(log(n))
сложность, так что это гораздо лучше, чем простой for
цикл, когда много элементов.
Вы можете использовать numpy, чтобы указать элементы, которые подчиняются условиям, а затем использовать argmax()
, чтобы получить индекс первого
import numpy
test_array = numpy.array([(1,2),(3,4),(5,6),(7,8),(9,10)])
min_value = 5
print (test_array[:,0]>min_value).argmax()
если вы хотите найти все элементы, которые соответствуют условию, используйте вместо argmax()
от nonzero()[0]
В общем, нампи where
используется аналогично MATLAB find
, Однако с точки зрения эффективности я where
невозможно контролировать, чтобы вернуть только первый найденный элемент. Итак, с вычислительной точки зрения, то, что вы здесь делаете, не менее неэффективно.
where
эквивалент будет
index = numpy.where(numpy.array([t[0] for t in test_array]) >= min_value)
index = index[0] - 1