【问题标题】:Sorting a dictionary both hierarchically and alphabetically (Python)按层次和字母顺序对字典进行排序(Python)
【发布时间】:2014-01-09 15:55:57
【问题描述】:

我正在使用 Python 字典 (product_dict) 来表示产品及其所有子部分的层次结构。 dict 的键是唯一 ID (UUID),值是包含有关这些部分的所有信息的 Class 对象,包括:

part.name        # A string, containing the actual name of a component
part.idCode      # UUID of component
part.parent      # UUID of parent component
part.children    # List of UUIDs of child components
part.tier        # An integer that specifies its tier/level within the hierarchy

现在为了有序地输出数据,我希望按层次和字母顺序对部分进行排序。对于使用树结构的分层排序,我发现这个问题的答案非常适合打印:Sorting data hierarchically。为了让这个示例与我的数据结构一起使用,我做了一些细微的修改:

class Node:
    def __init__(self, article):
        self.article = article
        self.children = []
        self.parent = None
        self.name = None 

    def printer(self, level=0):
        print ('{}{}'.format('\t' * level, self.name))
        for child in self.children:
            child.printer(level + 1)


class Tree:
    def __init__(self):
        self.nodes = {}

    def push(self, article, parent, name):                          
        if parent not in self.nodes:
            self.nodes[parent] = Node(parent)
        if article not in self.nodes:                              
            self.nodes[article] = Node(article)
        if parent == article:
            return
        self.nodes[article].name = name
        self.nodes[article].parent = self.nodes[parent]             
        self.nodes[parent].children.append(self.nodes[article])    

    @property
    def roots(self):
        return (x for x in self.nodes.values() if not x.parent)


t = Tree()

for idCode, part in product_dict.iteritems(): 
    t.push(idCode, part.parent, part.name)
for node in t.roots:
    node.printer()

考虑到我的产品是飞机的例子,现在的输出如下所示(实际顺序不同):

Aircraft
    Systems
        Subsystem 2
        Subsystem 1
            Subsubsystem 1.1
    Engines
    Airframe
        Section 2
        Section 1
        Section 4
        Section 3

但是,由于我现阶段对 Python 的了解有限,我正在努力将字母排序添加到此例程中(基于 part.name 字符串)。我了解树是如何构建的,但我不掌握打印例程,因此无法判断在哪里添加字母排序例程。

对于给定的示例,我想要的输出应该是:

Aircraft
    Airframe
        Section 1
        Section 2
        Section 3
        Section 4
    Engines     
    Systems
        Subsystem 1
            Subsubsystem 1.1
        Subsystem 2

非常感谢任何帮助。我不坚持上面给出的分层排序方法,所以我对完全不同的方法持开放态度。

【问题讨论】:

    标签: python sorting python-2.7 dictionary hierarchical-data


    【解决方案1】:

    似乎您唯一需要做的就是在打印时按名称对孩子进行排序,即

     for child in sorted(self.children, key = lambda x: x.name):
            child.printer(level + 1)
    

    【讨论】:

      【解决方案2】:

      给定一个分层字典:

      {
          UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"): {
              "id": UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"),
              "name": "D10:0:0",
              "code": "r0:0:0",
              "level": 0,
              "parent_id": None,
          },
          UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"): {
              "id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
              "name": "D11:0:0",
              "code": "r1:0:0",
              "level": 1,
              "parent_id": UUID("71f0967f-bfd3-43d5-883e-f3c971de141f"),
          },
          UUID("4c39d1e8-ba09-455c-8f76-866200531c51"): {
              "id": UUID("4c39d1e8-ba09-455c-8f76-866200531c51"),
              "name": "D12:0:0",
              "code": "r2:0:0",
              "level": 2,
              "parent_id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
          },
          UUID("8c4e89f2-7564-417f-88ba-1cbb3f9ac23f"): {
              "id": UUID("8c4e89f2-7564-417f-88ba-1cbb3f9ac23f"),
              "name": "D12:0:1",
              "code": "r2:0:1",
              "level": 2,
              "parent_id": UUID("f3dcaf21-66c9-48c5-9aae-f9ac84fc7d45"),
          }, ...
      }
      

      您可以通过键进行排序,保留层次结构:

      TD1 = typing.Dict[str, typing.Union[UUID, str, int, None]]
      TD1Dict = typing.Dict[UUID, TD1]
      def _sort_dict_hierarchy(dicts: TD1Dict, parent_id: typing.Optional[UUID] = None) -> TD1Dict:
          roots = [(k, v) for k, v in dicts.items() if v['parent_id'] == parent_id]
          sorted_dicts: TD1Dict = {}
          for k, v in sorted(roots, key=lambda r: r[1]['name']):
              sorted_dicts[k] = v
              sorted_dicts.update(_sort_dict_hierarchy(dicts, v['id']))
          return sorted_dicts
      
      

      测试:

      
      def create_dict_hierarchy(parent_id=None, level=0, pos=0, max_level=4):
          """Create a hierachy of dicts as we expect to be returned from oauth2."""
          dicts = {}
          for i in range(random.randrange(2, 4)):
              uid = uuid.uuid4()
              dicts[uid] = {
                  'id': uid,
                  'name': f'D1{level}:{pos}:{i}',
                  'code': f'r{level}:{pos}:{i}',
                  'level': level,
                  'parent_id': parent_id,
              }
              if level < max_level:
                  dicts.update(create_dict_hierarchy(uid, level+1, i, max_level))
          return dicts
      
      
      def test_sort_dict_hierarchy():
          """Sort dicts by nane in hirarchy."""
          dicts = create_dict_hierarchy(max_level=3)
          dicts_items = list(dicts.items())
          random.shuffle(dicts_items)
          shuffled_dicts = {k: v for k, v in dicts_items}
          assert list(dicts.keys()) != list(shuffled_dicts.keys())
      
          sorted_dicts = _sort_dict_hierarchy(shuffled_dicts)
      
          assert list(dicts.keys()) == list(sorted_dicts.keys())
      
      

      【讨论】:

        猜你喜欢
        • 2018-01-27
        • 1970-01-01
        • 1970-01-01
        • 2014-01-26
        • 2020-01-22
        • 2013-04-03
        • 2023-04-01
        • 1970-01-01
        相关资源
        最近更新 更多