Как получить несколько самых больших значений из списка?

Например у меня есть список:

arr = [1, 200, 400, 2, 100]

Как я могу получить три самых больших значений из списка?

То есть, должно получиться:

[400, 200, 100]

Пробовал функцию max(), но она возвращает только самое максимальное значение - 400.


Ответы (3 шт):

Автор решения: Gladius
arr = [1, 200, 400, 2, 100]
print(sorted(arr, reverse=True)[:3])
→ Ссылка
Автор решения: MaxU

Если у нас есть список размерности list_len и мы хотим найти N наибольших / наименьших элементов, то для случаев когда N << list_len (т.е. когда N значительно меньше list_len) разработчики Python рекомендуют использовать heapq.nlargest() / heapq.nsmallest():

heapq.nlargest(n, iterable, key=None) Return a list with the n largest elements from the dataset defined by iterable. key, if provided, specifies a function of one argument that is used to extract a comparison key from each element in iterable (for example, key=str.lower). Equivalent to: sorted(iterable, key=key, reverse=True)[:n].

The latter two functions perform best for smaller values of n. For larger values, it is more efficient to use the sorted() function. Also, when n==1, it is more efficient to use the built-in min() and max() functions. If repeated usage of these functions is required, consider turning the iterable into an actual heap.

from heapq import nlargest

res = nlargest(3, arr)

результат:

In [18]: res
Out[18]: [400, 200, 100]
→ Ссылка
Автор решения: CrazyElf

Ради интереса сравнил скорости этих сортировок на 100 000 элементах... И нашёл ещё более быстрый способ, кажется:

from heapq import nlargest
import random
import numpy as np

n = 100000
arr = list(range(n))
random.shuffle(arr)
arr_np = np.array(arr)

%timeit res_sorted = sorted(arr, reverse=True)[:3]
%timeit res_heapq = nlargest(3, arr)
%timeit res_np_sort = np.sort(arr_np)[-1:-4:-1]
%timeit res_np_part = -np.partition(-arr_np, 3)[:3]

Результат:

10 loops, best of 3: 41.3 ms per loop
100 loops, best of 3: 4.47 ms per loop
100 loops, best of 3: 8.25 ms per loop
1000 loops, best of 3: 1.09 ms per loop

Обычная сортировка понятно самая медленная - списки в питоне не очень быстрые, а тут приходится сортировать весь список.

nlargest отбирает элементы в 10 (!) раз быстрее. И это логично - ведь тут не нужно переставлять местами элементы или их индексы в огромном списке, а нужно только отобрать самые большие элементы в отдельный список.

Сортировка в Numpy работает в 2 раза медленнее, чем nlargest, но, учитывая, что она создаёт новый numpy.array того же размера, что и исходный, это, наверное, логично.

И, наконец, победитель - функция Numpy.partition, которая возвращает массив, в котором гарантированно отсортировано только заданное число элементов в начале массива. У неё нет сортировки по убыванию и приходится немного извращаться чтобы получить таковую, но работает она в итоге в 4 (!) раза быстрее, чем отбор максимальных элементов через nlargest. Numpy вообще очень сильно оптимизированная библиотека, я не удивлён.

Такие дела.

→ Ссылка