【问题标题】:Sorting a Python list by key... while checking for string OR float?按键排序Python列表...同时检查字符串或浮点数?
【发布时间】:2009-07-06 18:00:59
【问题描述】:

好的,我有一个这样的列表(只是一个数据样本):

data = {"NAME": "James", "RANK": "3.0", "NUM": "27.5" ... }

现在,如果我运行这样的东西:

sortby = "NAME" //this gets passed to the function, hence why I am using a variable sortby instead
data.sort(key=itemgetter(sortby))

我将所有字符串按字母顺序正确排序。

但是,当“sortby”是任何浮动值(RANK 或 NUM 或任何其他值)时,将再次按字母顺序而不是数字顺序进行排序,因此我的排序列表看起来像这样:

0.441 101.404 107.558 107.558 108.48 108.945 11.195 12.143 12.801 131.73

这显然是错误的。

现在,我怎么能做这样的排序(在速度和资源/计算方面最有效)但是让它以某种方式在它是一个浮点数时将值转换为浮点数,当它是一个字符串时将它保留为一个字符串... 可能的?不,从列表中的浮点值中删除引号不是一种选择 - 不幸的是,我无法控制源列表(我知道,这将是一个简单的解决方案)。

【问题讨论】:

    标签: python list sorting


    【解决方案1】:

    如果您想要一个可以作为参数传递给sort(key=XXX) 的通用函数,那么这里有一个完整的候选函数:

    DATA = [
        { 'name' : 'A', 'value' : '10.0' },
        { 'name' : 'B', 'value' : '2.0' },
    ]
    
    def get_attr(name):
        def inner_func(o):
            try:
                rv = float(o[name])
            except ValueError:
                rv = o[name]
            return rv
        return inner_func
    
    for attrname in ('name', 'value'):
        DATA.sort(key=get_attr(attrname))
        print "%r-sorted: %s" % (attrname, DATA)
    

    当你运行上面的脚本时,你会得到:

    'name'-sorted: [{'name': 'A', 'value': '10.0'}, {'name': 'B', 'value': '2.0'}]
    'value'-sorted: [{'name': 'B', 'value': '2.0'}, {'name': 'A', 'value': '10.0'}]
    

    【讨论】:

    • +1 — 非常 DWIMish,可能很容易扩展到其他类型。
    【解决方案2】:

    如果你不能正确保存你的数据(浮动为 floats),像这样

    sorters = { "NAME" : itemgetter("NAME"), 
                "RANK" : lambda x: float(x["RANK"]),
                "NUM" : lambda x: float(x["NUM"])
    }
    
    data.sort(key=sorters[sortby])
    

    【讨论】:

    • 我喜欢这样...从来没有想过为排序类型提供单独的字典。谢谢!唯一的问题是我需要将 50 多列转换为像这样浮动,但这是迄今为止最流畅的方法......
    • 查看我的答案,不需要单独的字典。这是一个很好的答案,但你必须设置那个 50-entry dict...
    • +1 — 随着列数的增加,我当然可以看到这变得很麻烦,但我真的很喜欢清晰和灵活。
    【解决方案3】:

    比仅仅传递一个字段名称稍微详细一点,但这是一个选项:

    sort_by_name = lambda x: x['name']
    sort_by_rank = lambda x: float(x['RANK'])
    # etc...
    
    data.sort(key=sort_by_rank)
    

    如果数据比您发布的数据密集得多,您可能需要一个单独的字典,将字段名称映射到数据类型,然后使用工厂函数生成适合 key 参数的分类器list.sort()

    【讨论】:

      猜你喜欢
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      • 2012-11-19
      • 1970-01-01
      • 2020-06-27
      相关资源
      最近更新 更多