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?
Use Python's min() and max() to find smallest and largest values in your data. Call min() and max() with a single iterable or with any number of regular arguments. Use min() and max() with strings and dictionaries.
The max() function prints the largest element in the list.
Short answer: To find the maximal list in a list of lists, you need to make two lists comparable. How? With the key argument of the max() function. The key argument is a function that takes one input (a list) and returns one output (a numerical value).
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With