【问题标题】:dictionary sort value by type字典按类型排序值
【发布时间】:2021-12-07 13:01:20
【问题描述】:

问题陈述:我有一个字典,其中值有许多不同的类型,如 int、str、list、class、class 属性、类方法等。我想通过type 进行值排序。就像字符串,列表一样,会先后休息。,

有人可以建议如何编写一个关键函数以便我可以控制sorting by type

class dummy:
    a = 1

obj = dummy()
x = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
x = dict(sorted(x.items() , key = lambda x:type(x[1]))) #It will fail as can't compare the type
print(x)

预期输出:

打印(x)

{'a':'abc','e': [1,2,3] ,'c':obj, 'd':obj.a, 'b':1}

【问题讨论】:

  • 如果您真的想这样做,请使用字典将类型映射到数值。但实际上,对字典进行排序并没有真正意义,因为字典的全部意义在于能够通过键而不是有序索引来查找值。对字典进行排序通常是没有意义的。
  • 谢谢。这是我项目中非常特殊的需求。

标签: python sorting dictionary


【解决方案1】:

可能有更好的方法来做到这一点,但这个例子有效:

>>> maps = {
    'str': 0,
    'list': 1,
    'int': 2,
    'dummy': 3
}

>>> dict(sorted(x.items(), key=lambda x: maps.get(type(x[1]).__name__, 999)))
{'a': 'abc', 'e': [1, 2, 3], 'b': 1, 'd': 1, 'c': <__main__.dummy object at 0x000001C1FEB8B250>}

替代(相同,但 lambda 被替换为完整的功能):

>>> maps = {
    'str': 0,
    'list': 1,
    'int': 2,
    'dummy': 3
}

>>> def sort_key(x):
    value = x[1]
    map_key =  type(value).__name__
    return maps.get(map_key, 999)

>>> dict(sorted(x.items(), key=sort_key))
{'a': 'abc', 'e': [1, 2, 3], 'b': 1, 'd': 1, 'c': <__main__.dummy object at 0x000001BE86F8BB50>}

【讨论】:

  • 有什么特别的理由不简单地使用{str: 0, ..., dummy: 3},而不是打电话给__name__吗?
  • 一开始我也想这么做。我确实做到了,而且奏效了。但是感觉很不对劲,所以我改用字符串表示来代替
  • 嗯,Python 中的一切都是对象。类和内置函数是可散列的。
  • 我唯一想说的是,为了清洁起见,可能考虑将排序键转换为命名函数。否则 +1。
  • 这是一个很好的观点,我将它作为替代方案包含在内
【解决方案2】:

作为sorted函数的关键,我推荐这个函数:

lambda x: (not isinstance(x[1], str), not isinstance(x[1], list), type(x[1]).__name__)

这将映射值如下:

  • 字符串到元组(False, True, 'str');
  • 列表到元组(True, False, 'list')
  • 元组(True, True, 'something else')的其他对象。

由于元组是按字典顺序排序的,而False &lt; True,这将把字符串放在第一位,列表在第二位,其他类型的值将按照类型名称的字母顺序排列。

使用您问题中提供的示例数据:

class dummy:
    a = 1

obj = dummy()
d = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
d = dict(sorted(d.items() , key = lambda x: (not isinstance(x[1], str), not isinstance(x[1], list), type(x[1]).__name__))) 

print(d)

{'a': 'abc',                                  # (False, True, 'str')
 'e': [1, 2, 3],                              # (True, False, 'list')
 'c': <__main__.dummy object at 0x10f311ba8>, # (True, True, 'dummy')
 'b': 1,                                      # (True, True, 'int')
 'd': 1                                       # (True, True, 'int')
}

【讨论】:

    【解决方案3】:

    我认为你可以使用 str 转换:

    class dummy:
        a = 1
    
    obj = dummy()
    x = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
    x = dict(sorted(x.items() , key = lambda x:str(type(x[1])))) #It will fail as can't compare the type
    print(x)
    

    【讨论】:

    • 这不会产生预期的结果,因为'list' &lt; 'str'
    • 您在 sorted reverse = True 中有第三个参数,或许多其他方法,如 slices
    猜你喜欢
    • 1970-01-01
    • 2019-09-28
    • 2017-02-02
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多