2010-05-04 18 views
15

¿Cuál es la forma idiomática de hacer maximumBy (función de orden superior tomando una función de comparación para la prueba), en una lista de listas, donde la comparación que queremos hacer es la suma de la lista, en Python?Encontrar el máximo de una lista de listas por suma de elementos en Python

Aquí es una aplicación y una salida de ejemplo Haskell:

> maximumBy (compare `on` sum) [[1,2,3],[4,5,6],[1,3,5]] 
> [4,5,6] 

e implementaciones de las funciones de la biblioteca de base, simplemente para la corrección (en caso de que desee utilizar reducir o algo :)

maximumBy cmp xs = foldl1 maxBy xs 
    where 
     maxBy x y = case cmp x y of GT -> x; _ -> y 

k `on` f = \x y -> f x `k` f y 

sum  = foldl' (+) 0 

Respuesta

42

Desde Python 2.5 puede usar max con un parámetro clave:

>>> max(a, key=sum) 
[4, 5, 6] 
+0

¡Haha, solución increíble! –

+3

+1. Corto, claro y preciso. Muy pitónico. –

+1

max (a) parece hacer lo mismo. – titaniumdecoy

1

No es muy eficiente, pero:

reduce(lambda x,y: x if sum(x)>sum(y) else y, [[1,2,3],[4,5,6],[1,3,5]]) 
+0

Comparando esto con la respuesta correcta de @ Mark es una forma deliciosa de mostrar por qué los programadores de Python estarían lejos de "olvidarse" de 'reducir' (¡ya no está incorporado en Py3! -). –

+6

@Alex: Si alguien hubiera publicado una respuesta usando un for-loop, que también habría sido mucho más torpe que la respuesta de Mark, ¿hubieras argumentado que a los programadores de Python les conviene olvidar los for-loops? – sepp2k

+2

@ sepp2k: los bucles 'for' son una forma deliciosa de mostrar por qué los programadores de Python deberían usar listas de comprensión. Con toda seriedad, no siempre hay un reemplazo para un ciclo 'for', pero ese no suele ser el caso de' reduce'. Aunque personalmente me gusta el 'map' /' filter'/'reduce' trinity, Alex tiene razón en que generalmente hay una mejor manera. – outis

1

si Max no tenía el parámetro clave que podría codificar el patrón ESD explícitamente:

max(izip(imap(sum,a),a))[1] 

izip y imap son desde el módulo de itertools python 2 y hacer lo que zip y map hacer, pero de forma perezosa usando generadores Python, para evitar tener una lista intermedia. En Python 3, el mapa y los builtins zip son flojos.

Cuestiones relacionadas