2012-06-11 31 views
6

Estos días diseño algunos algoritmos en python, pero encontrar los dos primeros valores más grandes en python es demasiado feo e ineficiente.Más forma pitónica de encontrar los dos primeros valores más importantes en una lista en python

¿Cómo implementarlo de una manera eficiente o pionera?

manera
+0

posible duplicado del filtro [max 20 valores de una lista de números enteros] (http://stackoverflow.com/questions/9757289/filter -max-20-values-from-a-list-of-integers) –

Respuesta

5

he encontrado que esto es consistentemente más rápido (aproximadamente 2x para una lista de artículos 1.000.000) que 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 

(función modificada por sugerencia de MatthieuW)

Aquí están los resultados ct de mis pruebas (timeit estaba tomando para siempre, por lo que utilizan 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

Debe comparar con el segundo, luego primero. En una lista de 1000000 elementos (a menos que esté ordenada), la mayoría será menos que el "segundo" actual, por lo que puede evitar una comparación por artículo. – MatthieuW

+0

@ MatthieuW: ¡Buen punto! De hecho, me sorprendió que un guión interpretado funcionara más rápido que cualquiera de los builtins. –

+1

Al menos en Python 2.7, el módulo 'heapq' también se implementa como un script Python interpretado, no como código C. Entonces su resultado no es tan sorprendente. – interjay

16

más Pythonic es utilizar nlargest:

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

O simplemente use el built-in ordenado. 'values ​​= sorted (my_list, reverse = True) [: 2]' –

+1

@Christian: Eso sería más lento y (en mi opinión) menos pitónico. – interjay

+2

@interjay: para listas pequeñas 'sort()' podría ser más rápido. – jfs

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

-1 para sugerir la clasificación. Esto es simplemente horrible. No es necesario ordenar para encontrar los dos elementos más grandes. –

+1

@MichaelWild, es cierto que la ordenación no es necesaria para ** n ** mayores números. Pero incluso [nlargest] (http://docs.python.org/library/heapq.html#heapq.nlargest) dice ** Equivalente a: ordenado (iterable, clave = clave, reversa = Verdadero) [: n] ** – tuxuday

+2

@tuxuday - es equivalente en el resultado, no en el rendimiento. Utiliza 'ordenado' solo cuando' n> tamaño'. – eumiro

Cuestiones relacionadas