My goal: Sort a list
of Products (dict
) first by Price, then by Name.
My problem: Str
values with numbers in them aren't sorted properly (AKA "Human sorting" or "Natural Sorting").
I found this function from a similar question: Python sorting list of dictionaries by multiple keys
def multikeysort(items, columns):
from operator import itemgetter
comparers = [((itemgetter(col[1:].strip()), -1) if col.startswith('-') else
(itemgetter(col.strip()), 1)) for col in columns]
def comparer(left, right):
for fn, mult in comparers:
result = cmp(fn(left), fn(right))
if result:
return mult * result
else:
return 0
return sorted(items, cmp=comparer)
The problem is that my Prices are str
type, like this:
products = [
{'name': 'Product 200', 'price': '3000.00'},
{'name': 'Product 4', 'price': '100.10'},
{'name': 'Product 15', 'price': '20.00'},
{'name': 'Product 1', 'price': '5.05'},
{'name': 'Product 2', 'price': '4.99'},
]
So they're getting sorted alphabetically, like this:
'100.10'
'20.10'
'3000.00'
'4.99'
'5.05'
Similarly, when I sort by name, I get this:
'Product 1'
'Product 15'
'Product 2'
'Product 200'
'Product 4'
The names should be listed in "human" order (1,2,15 instead of 1,15,2). Is it possible to fix this? I'm pretty new to python, so maybe I'm missing something vital. Thanks.
EDIT
More Info: I'm sending the list of products to a Django template, which requires the numbers to be properly formatted. If I float the prices and then un-float them, I have to iterate through the list of products twice, which seems like overkill.