【问题标题】:Custom Sorting Python Dictionary自定义排序 Python 字典
【发布时间】:2012-08-15 10:02:46
【问题描述】:

所以我有一本打印出来的字典是这样的:

{'10': -10, 'ZT21': 14, 'WX21': 12, '2': 15, '5': -3, 'UM': -25}

我想以我定义的自定义方式对这些进行排序。假设我希望它的排序方式(按键)是ZT21, 10, WX21, UM, 5, 2

有人知道如何以预定义/自定义的方式整理字典吗?我正在做的是从数据库中获取这本字典,它可以包含 20 多个键,所有键都有特定的顺序。总是设置顺序,但有时某些键/值不会在字典中。所以这也可能发生:

{'ZT21': 14, 'WX21': 12, '2': 15, '5': -3, 'UM': -25}

排序(按键)是ZT21, 10, WX21, UM, 5, 2

所以在这个例子中 10 不存在,但我需要的排序仍然是相同的,10 将不存在。

有什么想法吗?

【问题讨论】:

  • 到目前为止你尝试过什么?

标签: python


【解决方案1】:

你不能。请改用collections.OrderedDict

【讨论】:

    【解决方案2】:

    字典本质上是无序的,因此您不能直接对字典进行排序。您可以通过对someDict.items() 进行排序并传入一个键函数来对键/值对进行排序,就像对其他任何内容进行排序一样,但是您将得到一个排序列表而不是字典。请参阅之前关于字典排序的问题:例如Python: sorting a dictionary of listsDictionary sorting by key length

    【讨论】:

      【解决方案3】:

      Python 3.6+ 的更新答案

      >>> d = {'10': -10, 'ZT21': 14, 'WX21': 12, '2': 15, '5': -3, 'UM': -25}
      >>> keyorder = ['ZT21', '10', 'WX21', 'UM', '5', '2']
      >>> {k: d[k] for k in keyorder if k in d}
      {'ZT21': 14, '10': -10, 'WX21': 12, 'UM': -25, '5': -3, '2': 15}
      

      传统答案: Python 中的字典是无序的(在 Python3.6 之前)。您可以通过list 获得所需的结果

      >>> d = {'10': -10, 'ZT21': 14, 'WX21': 12, '2': 15, '5': -3, 'UM': -25}
      >>> keyorder = ['ZT21', '10', 'WX21', 'UM', '5', '2']
      >>> sorted(d.items(), key=lambda i:keyorder.index(i[0]))
      [('ZT21', 14), ('10', -10), ('WX21', 12), ('UM', -25), ('5', -3), ('2', 15)]
      

      或作为 OrderedDict

      >>> from collections import OrderedDict
      >>> OrderedDict(sorted(d.items(), key=lambda i:keyorder.index(i[0])))
      OrderedDict([('ZT21', 14), ('10', -10), ('WX21', 12), ('UM', -25), ('5', -3), ('2', 15)])
      

      如果你做了很多这些,使用dict作为keyorder会更有效

      >>> keyorder = {k:v for v,k in enumerate(['ZT21', '10', 'WX21', 'UM', '5', '2'])}
      >>> OrderedDict(sorted(d.items(), key=lambda i:keyorder.get(i[0])))
      OrderedDict([('ZT21', 14), ('10', -10), ('WX21', 12), ('UM', -25), ('5', -3), ('2', 15)])
      

      【讨论】:

      • 好吧,我绝对不介意它不在字典形式中,我只是希望它从来自数据库的字典形式到我可以打印的顺序的列表中。看来您的解决方案正在实现这个想法,如果我尽快让它工作,会回复!
      • 优秀的答案!旁白:如果你有嵌套的字典——例如{"0":{"0":{"obj":"book", "rel":"gave", "subj":"Victoria"}}, "1":{"0":{"obj":"it","rel":"loved","subj":"She"}}} -- 可以对最里面的键进行排序,keyorder = ['subj', 'rel', 'obj'] 如下:for i in range(len(dict)): for j in range(len(dict[i])): sorted_dict = sorted(relations_dict[i][j].items(), key=lambda item:keyorder.index(item[0]))
      • .index(i[0]) 是如何工作的?我不明白该行如何使用每个字符串中的第二个、第三个等字符对项目进行排序。您的答案有效,看起来不错,但没有解释它如何或为什么起作用。你的第一条评论也是错误的。从 python 3.6 开始,字典键是有序的。
      • @Anthony,每一项都是(字符串,数字)的元组,所以 i[0] 指的是元组的字符串部分。 Python 3.6 是在写完这个答案 4 年后发布的 :)
      • @JohnLaRooy 感谢您的回复。
      【解决方案4】:

      我遇到了完全相同的问题,并设计了一个轻量级的通用解决方案:

      from collections import OrderedDict
      
      def make_custom_sort(orders):
          orders = [{k: -i for (i, k) in enumerate(reversed(order), 1)} for order in orders]
          def process(stuff):
              if isinstance(stuff, dict):
                  l = [(k, process(v)) for (k, v) in stuff.items()]
                  keys = set(stuff)
                  for order in orders:
                      if keys.issuperset(order):
                          return OrderedDict(sorted(l, key=lambda x: order.get(x[0], 0)))
                  return OrderedDict(sorted(l))
              if isinstance(stuff, list):
                  return [process(x) for x in stuff]
              return stuff
          return process
      

      首先,您创建一个自定义排序函数的实例:

      custom_sort = make_custom_sort([ ['ZT21', '10', 'WX21', 'UM', '5', '2'] ])
      

      现在,实际排序:

      result = custom_sort(my_dataset)
      

      最后以未指定的顺序拒绝丢失的键。请注意,此闭包是递归的。如双括号所示,您可以指定嵌套在结构中的各种字典所需的排序顺序。

      GitHub 上的项目:https://github.com/laowantong/customsort

      【讨论】:

      • “订单”是一系列物品,还是客户要求的东西? :-)
      • 据我记得,这是一个按客户希望在稍后传递给custom_sort的子字典中排序的键列表。
      【解决方案5】:

      您可以使用 OrderedDict 并指定您的自定义顺序对其进行排序。

      def customsort(dict1 , key_order):
          items = [dict1[k] if k in dict1.keys() else 0 for k in key_order] 
          sorted_dict = OrderedDict()
          for i in range(len(key_order)):
              sorted_dict[key_order[i]] = items[i]
          return sorted_dict
      key_order = [ "monday" ,"tuesday" ,"wednesday" ,"thursday" ,"friday" ,"saturday"]
      dict1 ={"monday" : 10 , "thursday" :12 , "wednesday" : 34}
      sorted_dicti = customsort(dict1,key_order)
      print(sorted_dicti)
      

      customsort() 按用户传递的 order(key_order) 对给定字典(dict1) 进行排序。

      items = [dict1[k] if k in dict1.keys() else 0 for k in key_order] 
      

      它将检查给定的键是否在dict1中,如果存在则将值放入dict1中,否则将值设置为0。

      OrderedDict([('monday', 10), ('tuesday', 0), ('wednesday', 34), ('thursday', 12), ('friday', 0), ('saturday', 0)])
      

      【讨论】:

        猜你喜欢
        • 2016-10-15
        • 2018-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多