views:

334

answers:

2

What's the idiomatic way to do maximumBy (higher order function taking a comparison function for the test), on a list of lists, where the comparison we want to make is the sum of the list, in Python?

Here's a Haskell implementation and example output:

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

And implementations of those base library functions, just for completeness (in case you want to use reduce or something :)

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
+21  A: 

Since Python 2.5 you can use max with a key parameter:

>>> max(a, key=sum)
[4, 5, 6]
Mark Byers
Haha, awesome solution!
Xavier Ho
+1. Short, clear and precise. Very pythonic.
Noufal Ibrahim
max(a) seems to do the same thing.
titaniumdecoy
@titaniumdecoy: The default behaviour is a lexicographical ordering which by chance happens to give the same result for this input data, but in general can give a different answer.
Mark Byers
+1  A: 

It isn't terribly efficient, but:

reduce(lambda x,y: x if sum(x)>sum(y) else y, [[1,2,3],[4,5,6],[1,3,5]])
outis
Comparing this with @Mark's correct answer is a delightful way to show why Python programmers would be by far best off _forgetting_ about `reduce` (good thing it's not a built-in any more in Py3!-).
Alex Martelli
@Alex: If someone had posted an answer using a for-loop, which would have also been much clumsier than Mark's answer, would you have argued that python programmers are better off forgetting about for-loops?
sepp2k
@sepp2k: `for` loops are a delightful way of showing why Python programmers should use list comprehensions. In all seriousness, there isn't always a replacement for a `for` loop, but that's usually not the case for `reduce`. As much as I personally like the `map`/`filter`/`reduce` trinity, Alex is right in that there usually is a better way.
outis
@outis, I would say "there usually is a better way _in Python_" -- I wouldn't say it without the qualification since it may not be the case in, e.g., Haskell or Lisp. But, we do agree on the gist;-).
Alex Martelli
You can only eliminate the `reduce` in this case because `max` is itself essentially `reduce` hard-coded to use the binary `max` function. This does nothing whatsoever to demonstrate that `reduce` isn't useful in the general case. It just demonstrates that if, for your particular case, there is a specialised function, you should use it.
@Alex: indeed, that is what I meant (since we're dealing w/ Python). If we were discussing Common Lisp...
outis