2012-06-11 3 views
6

В настоящее время я разрабатываю некоторые алгоритмы в python, но найти первые два величайших значения в python слишком уродливые и неэффективные.Подробнее pythonic способ найти первые два наибольших значения в списке в python

Как реализовать его эффективным или путинским способом?

+0

возможно дубликат [Фильтр макс 20 значений из списка целых чисел] (http://stackoverflow.com/questions/9757289/filter -max-20-values-from-a-list-of-integers) –

ответ

5

Я нашел, что это будет последовательно быстрее (примерно в 2 раза для списка 1000000 элементов), чем heapq.nlargest:

def two_largest(sequence): 
    first = second = 0 
    for item in sequence: 
     if item > second: 
      if item > first: 
       first, second = item, first 
      else: 
       second = item 
    return first, second 

(функция, модифицированная по предложению MatthieuW)

Здесь приведены результаты ц моего тестирования (timeit принимает навсегда, так что я использовал time.time()):

>>> from random import shuffle 
>>> from time import time 
>>> seq = range(1000000) 
>>> shuffle(seq) 
>>> def time_it(func, *args, **kwargs): 
...  t0 = time() 
...  func(*args, **kwargs) 
...  return time() - t0 
... 

>>> #here I define the above function, two_largest(). 
>>> from heapq import nlargest 
>>> time_it(nlargest, 2, seq) 
0.258958101273 
>>> time_it(two_largest, seq) 
0.145977973938 
+1

Вы должны сравнить со вторым, затем первым. В списке 1000000 элементов (если он не отсортирован), большинство будет меньше текущего «второго», поэтому вы можете избежать одного сравнения для каждого элемента. – MatthieuW

+0

@MatthieuW: Хорошая точка! Я был действительно удивлен, что интерпретируемый скрипт работал быстрее, чем любой из встроенных. –

+1

По крайней мере, на Python 2.7 модуль 'heapq' также реализуется как интерпретируемый скрипт Python, а не как код C. Таким образом, ваш результат не настолько удивителен. – interjay

16

Наиболее Pythonic способ заключается в использовании nlargest:

import heapq 
values = heapq.nlargest(2, my_list) 
+1

Или просто используйте встроенную сортировку. 'values ​​= sorted (my_list, reverse = True) [: 2]' –

+1

@Christian: Это было бы медленнее и, по моему мнению, меньше Pythonic. – interjay

+2

@interjay: для небольших списков 'sort()' может быть быстрее. – jfs

1
mylist = [100 , 2000 , 1 , 5] 
mylist.sort() 
biggest = mylist[-2:] 
+3

-1 для предложения сортировки. Это просто ужасно. Не нужно сортировать, чтобы найти самые большие два элемента. –

+1

@MichaelWild, это правда, что сортировка не нужна для ** n ** крупнейших nos. Но даже [nlargest] (http://docs.python.org/library/heapq.html#heapq.nlargest) говорит ** Эквивалент: отсортирован (итерируемый, key = key, reverse = True) [: n] ** – tuxuday

+2

@tuxuday - это эквивалентно в результате, а не в производительности. Он использует 'sorted' только когда' n> size'. – eumiro

Смежные вопросы