In one form or other, you will want to put the products and the items together into some kind of collection, then use the total as the key for sorting but return the name.
In every case, the key argument to sort contains a reference to a function which takes one of the elements being sorted and returns a key to use for determining the sort position of that element.
Example with list of 2-tuples. (item, total)
def top3(products, amounts, prices):
item_totals = []
for item, num1, num2 in zip(products, amounts, prices):
item_totals.append((item, num1 * num2))
item_totals.sort(key=lambda t: t[1], reverse=True)
return [t[0] for t in item_totals]
Here, the lambda t: t[1] is used to construct a function which takes the 2-tuple and returns the second item, i.e. the total. It is equivalent to defining a little function:
def get_sort_key(t):
return t[1]
and then passing the function:
item_totals.sort(key=get_sort_key, reverse=True)
Example with list of dictionaries
For better readability instead of using a list of 2-tuples, we could have a list of dictionaries with keys 'item' and 'total':
def top3(products, amounts, prices):
item_totals = []
for item, num1, num2 in zip(products, amounts, prices):
item_totals.append({'item': item, 'total': num1 * num2})
item_totals.sort(key=lambda t: t['total'], reverse=True)
return [t['item'] for t in item_totals]
In that case, a function that you could use instead of the lambda can be generated by using itemgetter from the operator package. You would use:
from operator import itemgetter
and the call to sort can then be changed to:
item_totals.sort(key=itemgetter('total'), reverse=True)
Example with single dictionary
We could also just put everything into one dictionary, with the product as the key and the total as the value. But in this case, it relies on the names not being duplicated.
def top3(products, amounts, prices):
item_totals = {}
for item, num1, num2 in zip(products, amounts, prices):
item_totals[item] = num1 * num2
return sorted(item_totals.keys(),
key=lambda item: item_totals[item],
reverse=True)
There are more compact ways to write all of these, which avoid the need for the explicit for loop when building the collection prior to sorting, as demonstrated by some of the other answers, but this is the general principle.