tags:

views:

77

answers:

4

I'm new to Python and I really love the min function.

>>>min([1,3,15])
0

But what if I have a list of instances, and they all have a variable named number?

class Instance():
    def __init__(self, number):
        self.number = number

i1 = Instance(1)
i2 = Instance(3)
i3 = Instance(15)
iList = [i1,i2,i3]

Do I really have to something like

lowestI = iList[0].number
for i in iList:
    if lowestI > iList[i].number: lowestI = iList[i].number
print lowestI

Can't I use min in a nice pythonic way?

+9  A: 

The OOP way would be to implement __lt__:

class Instance():
    def __init__(self, number):
        self.number = number

    def __lt__(self, other):
        return self.number < other.number
        # now min(iList) just works

Another way is

imin = min(iList, key=lambda x:x.number)

Functions like sort, min, max all take a key argument. You give a function that takes an item and returns whatever should stand for this item when comparing it.

THC4k
+9  A: 
from operator import attrgetter
min( iList, key = attrgetter( "number" ) )

The same key argument also works with sort, for implementing the decorate-sort-undecorate idiom Pythonically.

katrielalex
`min( iList, key = attrgetter( "number" ) )`
leoluk
@leoluk: thanks!
katrielalex
attrgetter and itemgetter rock - a lot of lambda functions can be eliminated by using them. They are faster than lambda and IMHO easier to read.
Dave Kirby
+1 for `operator`!
jathanism
+1  A: 
min(iList, key=lambda inst: inst.number)
leoluk
Oops, too late.
leoluk
+4  A: 

Generator syntax:

min(i.number for i in iList)

key function:

min(iList, key=lambda i: i.number)
John Kugelman
`key` is better than generator as it keeps the reference to the instance.
leoluk