web-dev-qa-db-fra.com

Python: prendre max N éléments d'une liste

Y a-t-il une fonction qui me retournerait les N éléments les plus élevés d'une liste?

C'est à dire. si max(l) renvoie l'élément le plus élevé, sth. comme max(l, count=10) me renverrait une liste des 10 nombres les plus élevés (ou moins si l est plus petit).

Ou quel serait un moyen simple et efficace de les obtenir? (À l'exception de l'implémentation canonique évidente; également, aucune de ces choses qui impliquent de trier la liste entière en premier car cela serait inefficace par rapport à la solution canonique.)

36
Albert

heapq.nlargest :

>>> import heapq, random
>>> heapq.nlargest(3, (random.gauss(0, 1) for _ in xrange(100)))
[1.9730767232998481, 1.9326532289091407, 1.7762926716966254]
55
Gareth Rees

La fonction dans la bibliothèque standard qui fait cela est heapq.nlargest

6
Dave Webb

Commencez par les 10 premiers de L, appelez cela X. Notez la valeur minimale de X.

Boucle sur L [i] pour i sur le reste de L.

Si L [i] est supérieur à min (X), supprimez min (X) de X et insérez L [i]. Vous devrez peut-être conserver X en tant que liste liée triée et effectuer une insertion. Mettre à jour min (X).

À la fin, vous avez les 10 plus grandes valeurs de X.

Je soupçonne que ce sera O(kN) (où k est 10 ici) car le tri par insertion est linéaire. Peut-être ce que gsl utilise, donc si vous pouvez lire du code C:

http://www.gnu.org/software/gsl/manual/html_node/Selecting-the-k-smallest-or-largest-elements.html

Probablement quelque chose en numpy qui fait ça.

3
Spacedman

Une solution assez efficace est une variation de tri rapide où la récursivité est limitée à la partie droite du pivot jusqu'à ce que la position du point de pivot soit supérieure au nombre d'éléments requis (avec quelques conditions supplémentaires pour faire face aux cas de frontière bien sûr).

La bibliothèque standard a heapq.nlargest, comme l'ont souligné d'autres ici.

1