Получите немедленный минимум среди списка чисел в python
Как я могу получить следующее минимальное значение для значения, предоставляемого в python? Есть ли встроенные функции для этого?
>>>num_list=[1,2,3,4]
>>> min(num_list)
1
>>> max(num_list)
4
Как я могу найти следующий минимум до 3 или следующего по величине до 2? Ожидаемые результаты равны 2 и 3.
Ответы
Ответ 1
TL; DR Либо min(n for n in my_list if n>lower_bound)
, либо max(n for n in my_list if n<upper_bound)
Более быстрая альтернатива для нахождения ближайшего минимума или ближайшего максимума numpy
>>> import numpy as np
>>> np.random.seed(10)
>>> a = np.random.random(10000)
>>> a[a>0.7].min()
0.69999533217645671
>>> a[a<0.7].max()
0.70003449227846715
Если вам неудобно использовать оборудование numpy
и хотите иметь дело просто со списком
>>> a = list(a)
то вы можете использовать встроенные функции min
и max
вместе с генератором
выражения
>>> min(n for n in a if n>0.7)
0.69999533217645671
>>> max(n for n in a if n<0.7)
0.70003449227846715
>>>
Используя списки, у вас есть, конечно, те же результаты, но будьте осторожны, что есть разница в производительности: используя ipython
и %timeit
, чтобы получить тайминги, у меня было 871 мкс с использованием numpy
и 13,8 мс, используя регулярные списки для массива/списка 100000 элементов предыдущих примеров.
HTH, ciao
Post Scriptum
Решениями в моем ответе являются все O (n) по сравнению с O (n log n) методов, которые используют сортировку --- далее, для больших наборов данных подход numpy
должен (курсив, потому что у меня нет тестирование под рукой...) зависит от небольшого мультипликативного фактора.
Ответ 2
следующий минимум до 3:
max([x for x in num_list if x < 3])
следующая наибольшая до 2:
min([x for x in num_list if x > 2])
Ответ 3
Я вижу, что ваш вопрос помечен тегами [lower-bound] и [upperbound]. Если ваш список отсортирован, Python имеет эквивалент С++ <algorithm> lower_bound
и upper_bound
. Они находятся в модуле bisect
. Они возвращают индексы начала и сразу после окончания диапазона определенного значения.
In [1]: import bisect
In [2]: A = [0, 1, 3, 3, 5]
In [3]: A[bisect.bisect_left(A, 3)-1]
Out[3]: 1
In [4]: A[bisect.bisect_right(A, 3)]
Out[4]: 5
Ответ 4
Вы можете использовать sorted
:
>>> l=sorted(num_list,reverse=True)
>>> l[l.index(3)+1]
2
Но как более питонический путь, как говорит Фририк Раабе в комментарии, вам не нужно болеть за весь список, вы можете найти максимальное значение для элементов, которые меньше 3:
>>> max(i for i in num_list if i<3)
2
И для следующего наибольшего после 2 вы можете использовать min
:
>>> min(i for i in num_list if i>2)
3
Ответ 5
Используйте heapq.nlargest
и heapq.nsmallest
import heapq
num_list = [1, 2, 3, 4]
heapq.nlargest(2, num_list)
heapq.nsmallest(2, num_list)
#>>> [4, 3]
#>>> [1, 2]
Ответ 6
Вы можете использовать следующий подход:
num_list = [1,2,3,4]
inds = sorted(range(len(num_list)), key=lambda k: num_list[k])
Затем inds [1] будет содержать индекс следующего нижнего элемента и т.д.
Кроме того, вы можете использовать следующий код без сортировки:
minv = min(num_list)
nmin = min(nm for nm in num_list if nm > minv)
maxv = max(num_list)
nmax = max(nm for nm in num_list if nm < maxv)
Ответ 7
Предоставленные ответы хороши, но если бы я мог сделать предложение - если бы были когда-нибудь повторяющиеся значения, например
num_list = [2, 2, 4, 4, 6, 7, 8, 9]
... и т.д., просто сортировка списка и получение первого индекса могут быть не тем, что вы ищете.
Пройдя сначала через set()
, вы убедитесь, что каждая запись является одиночной:
def sorted_ordered_list(sequence):
return sorted(list(set(sequence)))
Затем вы можете просто индексировать возвращенный list
для любого значения, которое вы ищете, от самого низкого значения с индексом 0 до самого высокого.
Пример:
>>> my_list = [1, 5, 4, 3, 6, 3, 8, 3, 6, 7, 4, 2, 6, 7, 9, 8, 8]
>>> sorted_ordered_list(my_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9] # now index the list for the desired value
>>>