我的目标:首先按价格排序list
个产品(dict
),然后按名称排序。
我的问题:Str
值中包含数字的值未正确排序(AKA“人类排序”或“自然排序”)。
我从类似的问题中找到了这个函数: 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)
问题是我的价格是str
类型,如下所示:
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'},
]
所以他们按字母顺序排序,如下:
'100.10'
'20.10'
'3000.00'
'4.99'
'5.05'
同样,当我按姓名排序时,我得到了这个:
'Product 1'
'Product 15'
'Product 2'
'Product 200'
'Product 4'
名称应以“人类”顺序列出(1,2,15而不是1,15,2)。有可能解决这个问题吗?我对python很新,所以也许我错过了一些重要的东西。感谢。
修改
更多信息:我将产品列表发送到Django模板,这需要正确格式化数字。如果我浮动价格然后解除它们,我必须两次遍历产品列表,这似乎有点过头了。
答案 0 :(得分:3)
您的排序功能过度。试试这个简单的方法:
from pprint import pprint
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'},
]
sorted_products = sorted(products, key=lambda x: (float(x['price']), x['name']))
pprint(sorted_products)
结果:
[{'name': 'Product 2', 'price': '4.99'},
{'name': 'Product 1', 'price': '5.05'},
{'name': 'Product 15', 'price': '20.00'},
{'name': 'Product 4', 'price': '100.10'},
{'name': 'Product 200', 'price': '3000.00'}]
我的解决方案的本质是让key
函数返回排序条件的元组。元组总是按字典顺序进行比较,因此第一项是主要排序,第二项是次要排序,依此类推。
答案 1 :(得分:2)
我认为最好的办法是将价格解析为浮点数(这样你就可以对它们进行排序):
float("1.00")
# output: 1.0
然后输出两位小数:
"{:.2f}".format(1.0)
# output: "1.00"
答案 2 :(得分:1)
尝试将问题类型转换为问题中的浮点数,当您需要打印2个小数位时,您可以轻松地格式化输出:
float_num = float("110.10")
print "{0:.2f}".format(float_num) # prints 110.10
答案 3 :(得分:0)
要断开关系,如果使用产品中的整数值对字符串进行排序,则可以返回元组:
products = [
{'name': 'Product 200', 'price': '2.99'},
{'name': 'Product 4', 'price': '4.99'},
{'name': 'Product 15', 'price': '4.99'},
{'name': 'Product 1', 'price': '9.99'},
{'name': 'Product 2', 'price': '4.99'},
]
def key(x):
p, i = x["name"].rsplit(None, 1)
return float(x["price"]), p, int(i)
sorted_products = sorted(products, key=key)
哪会给你:
[{'name': 'Product 200', 'price': '2.99'},
{'name': 'Product 2', 'price': '4.99'},
{'name': 'Product 4', 'price': '4.99'},
{'name': 'Product 15', 'price': '4.99'},
{'name': 'Product 1', 'price': '9.99'}]
相反:
[{'name': 'Product 200', 'price': '2.99'},
{'name': 'Product 15', 'price': '4.99'},
{'name': 'Product 2', 'price': '4.99'},
{'name': 'Product 4', 'price': '4.99'},
{'name': 'Product 1', 'price': '9.99'}]
仅使用float(x['price']), x['name']