【问题标题】:How to sort the keys of a dictionary in Python? [duplicate]如何在 Python 中对字典的键进行排序? [复制]
【发布时间】:2017-08-19 20:31:25
【问题描述】:

我有一个字典,它的键是整数,但是当迭代它时,我希望整数以未排序的顺序出现。在一个简单的例子中,这似乎适用于OrderedDict:

In [16]: d3 = OrderedDict({k: k+1 for k in [3, 2, 1]})

In [17]: for k, v in d3.items():
    ...:     print(k, v)
    ...:     
3 4
2 3
1 2

但是,在我的“真实”应用程序中,这并没有按预期工作。我正在尝试识别有向图的强连通分量 (SCC)。在我的Graph 类中,我正在编写strongly_connected_component 方法:

import pytest
import collections


class Node(object):
    def __init__(self):
        self.color = 'white'
        self.parent = None
        self.d = None           # Discovery time
        self.f = None           # Finishing time


class Graph(object):
    def __init__(self, edges):
        self.edges = edges
        self.nodes = self.initialize_nodes()
        self.adj = self.initialize_adjacency_list()

    def initialize_nodes(self, node_indices=None):
        if node_indices is None:
            node_indices = sorted(list(set(node for edge in self.edges for node in edge)))
        return collections.OrderedDict({node_index: Node() for node_index in node_indices})

    def initialize_adjacency_list(self):
        A = {node: [] for node in self.nodes}
        for edge in self.edges:
            u, v = edge
            A[u].append(v)
        return A

    def dfs(self):
        self.time = 0
        for u, node in self.nodes.items():
            if node.color == 'white':
                self.dfs_visit(u)

    def dfs_visit(self, u):
        self.time += 1
        self.nodes[u].d = self.time
        self.nodes[u].color = 'gray'
        for v in self.adj[u]:
            if self.nodes[v].color == 'white':
                self.nodes[v].parent = u
                self.dfs_visit(v)
        self.nodes[u].color = 'black'
        self.time += 1
        self.nodes[u].f = self.time

    @staticmethod
    def transpose(edges):
        return [(v,u) for (u,v) in edges]

    def strongly_connected_components(self):
        self.dfs()
        finishing_times = {u: node.f for u, node in self.nodes.items()}
        # print(finishing_times)
        self.__init__(self.transpose(self.edges))
        node_indices = sorted(finishing_times, key=self.nodes.get, reverse=True)
        # print(node_indices)
        self.nodes = self.initialize_nodes(node_indices)
        # print(self.nodes)

为了验证dfs 方法是否有效,我复制了以下来自 Cormen 等人的示例,算法简介:

我将节点标签 u 到 z 分别替换为数字 1 到 6。下面的测试,

def test_dfs():
    '''This example is taken from Cormen et al., Introduction to Algorithms (3rd ed.), Figure 22.4'''
    edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
    graph = Graph(edges)
    graph.dfs()

    print("\n")
    for index, node in graph.nodes.items():
        print index, node.__dict__

打印

1 {'color': 'black', 'd': 1, 'parent': None, 'f': 8}
2 {'color': 'black', 'd': 2, 'parent': 1, 'f': 7}
3 {'color': 'black', 'd': 9, 'parent': None, 'f': 12}
4 {'color': 'black', 'd': 4, 'parent': 5, 'f': 5}
5 {'color': 'black', 'd': 3, 'parent': 2, 'f': 6}
6 {'color': 'black', 'd': 10, 'parent': 3, 'f': 11}

很容易看出它与书中的图 22.4(p) 相对应。为了计算 SCC,我必须实现以下伪代码:

在我的strongly_connected_components 方法中,我通过完成时间以相反的顺序订购node_indices。由于它在initialize_nodes 方法中被初始化为OrderedDict,因此我希望通过以下测试:

def test_strongly_connected_components():
    edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
    graph = Graph(edges)
    graph.strongly_connected_components()
    assert graph.nodes.keys() == [3, 2, 1, 4, 6, 5]


if __name__ == "__main__":
    pytest.main([__file__, "-s"])

因为[3, 2, 1, 4, 6, 5] 是深度优先搜索中节点“完成”的相反顺序。但是,此测试失败:

=================================== FAILURES ===================================
______________________ test_strongly_connected_components ______________________

    def test_strongly_connected_components():
        edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
        graph = Graph(edges)
        graph.strongly_connected_components()
>       assert graph.nodes.keys() == [3, 2, 1, 4, 6, 5]
E    assert [1, 2, 3, 4, 5, 6] == [3, 2, 1, 4, 6, 5]
E      At index 0 diff: 1 != 3
E      Use -v to get the full diff

scc.py:94: AssertionError

为什么键没有按照OrderedDict初始化时指定的顺序保留?

【问题讨论】:

标签: python algorithm graph


【解决方案1】:

您正在使用常规字典初始化 OrderedDict,因此您会立即失去排序。使用可迭代的键值对对其进行初始化。

【讨论】:

  • 领先我几秒。不过,某处可能有重复。找到了。
  • @Jean-FrançoisFabre:啊,就是这样。我以为某处可能有一个,但我最初的搜索没有找到它。
  • 那是因为你使用的是垃圾搜索...使用谷歌确保找到它(至少有2个骗子,我只是链接它们)
  • 为了完整起见,我将initialize_nodes 中的违规行替换为return collections.OrderedDict([(node_index, Node()) for node_index in node_indices]),从而解决了问题。
猜你喜欢
  • 2021-06-28
  • 2013-09-27
  • 2013-03-14
  • 2010-10-09
  • 2015-11-03
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多