Reputation: 1132
In Python I want to find the max element in a list using a lambda for comparison.
No success with this code:
# An 'anonymous' object, like JSON object. Use like: Mock(name='Bob', age=30)
class Mock(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
items = [
Mock(cost=10, quantity=1),
Mock(cost=15, quantity=3),
Mock(cost=20, quantity=5),
Mock(cost=100, quantity=2)
]
index, value = max(items, key=lambda(item) : item.cost * item.quantity)
print('$%d, q=%d' % (value.cost, value.quantity))
I get this error:
index, value = max(items, key=lambda(item) : item.cost * item.quantity)
TypeError: 'Mock' object is not iterable
How can I implement this correctly?
Upvotes: 6
Views: 9945
Reputation: 12391
If you don't need the index, you can use the result directly:
value = max(items, key=lambda(item) : item.cost * item.quantity)
print value.cost, value.quantity
max
returns the actual max item, which is a Mock
instance. You can't unpack it into two items.
If you really want the index, you can either find it, or modify your search a little bit to decorate the index into the item:
index, value = max(enumerate(items), key=lambda(item): item[1].cost * item[1].quantity)
First, we convert the original list into a second list where each item is a tuple of (index, value). Then, the key also has to change, because instead of item.cost
, item
is now an (index, MockItem)
pair, and so you need to get item[1]
, then get the attributes. Don't forget to unpack the result into index and value to get both.
Upvotes: 8
Reputation: 7545
This is not the most efficient way but it's easy for anyone reading it to understand. If you have very large lists, let me know and I'll point you to more efficient solutions.
# get the value
max_item = max(items, key=lambda item: item.cost * item.quantity)
# get the index
max_item_index = items.index(max_item)
If you also want the calculated value, then just do a loop to keep it clear:
max_value = max_index = max_item = None
for i, item in enumerate(items):
value = item.cost * item.quantity
if (max_value is None) or (value > max_value):
max_value = value
max_index = i
max_item = item
if max_value is not None:
print max_index, max_value, max_item
Upvotes: 2