Прежде всего, не совсем ясно, что двоичный поиск здесь оправдан , Вполне возможно, что линейный поиск выполняется быстрее, когда количество интервалов невелико.
Если вас беспокоит производительность, разумная задача - профилировать код и, возможно, сравнить оба метода на ваших типичных входах.
Отказ в сторону, бинарный поиск может быть реализован путем сортировки интервалов один раз, а затем многократно используя bisect
модуль для выполнения поиска:
import bisect
intervals = [(999, 2333, 'int1'), (0, 128, 'int2'), (235, 865, 'int3')]
intervals.sort()
def find_int(intervals, val):
pos = bisect.bisect_left([interval[1] for interval in intervals], val)
if pos < len(intervals) and val >= intervals[pos][0]:
return intervals[pos]
else:
return None
print(find_int(intervals, 0))
print(find_int(intervals, 1))
print(find_int(intervals, 200))
print(find_int(intervals, 998))
print(find_int(intervals, 999))
print(find_int(intervals, 1000))
print(find_int(intervals, 2333))
print(find_int(intervals, 2334))
В выше, я полагаю, что интервалы не перекрываются , и что этот интервал включает как начальную, так и конечную точки.
Наконец, чтобы повысить производительность, можно было бы рассмотреть факторинг [interval[1] for interval in intervals]
вне функции и сделать это только один раз в начале.
Действительно ли это «стоит» сортировки, чтобы использовать бинарный поиск? [Если вы планируете искать несколько раз, это не «стоит» сортировки, если вы планируете много раз искать] – amit
Объекты должны быть отсортированы. – rplnt
Какова абсолютная верхняя и нижняя граница этих чисел? Вы можете расширить диапазоны в соответствующий «бит-преобразованный индекс», где вы просто перечисляете все значения в диапазоне. –