Python用两个小数点排序str价格

时间:2016-08-08 23:23:49

标签: python sorted

我的目标:首先按价格排序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模板,这需要正确格式化数字。如果我浮动价格然后解除它们,我必须两次遍历产品列表,这似乎有点过头了。

4 个答案:

答案 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']