Python 迭代3个字典(关注速度)

Python 迭代3个字典(关注速度),python,for-loop,dictionary,nested-loops,networkx,Python,For Loop,Dictionary,Nested Loops,Networkx,我是Python新手,正在使用它构建图形 在我的脚本中,我有三个字典,它们可能需要相互嵌套: dict1={'Node ID':1}->dict1={'0':1,'1':1,'2':1,…} dict2={'Node ID':G.neights(Node ID)}->dict2={'0':[1,2,4],…} dict3={'Node ID':Status}->dict3={'1':1,'2':0,'4':1} 非常清楚,dict1告诉我节点是活动的(1)还是失败的(0)[在这种情况下,dict

我是Python新手,正在使用它构建图形

在我的脚本中,我有三个字典,它们可能需要相互嵌套:

  • dict1={'Node ID':1}->
    dict1={'0':1,'1':1,'2':1,…}
  • dict2={'Node ID':G.neights(Node ID)}->
    dict2={'0':[1,2,4],…}
  • dict3={'Node ID':Status}->
    dict3={'1':1,'2':0,'4':1}
  • 非常清楚,
    dict1
    告诉我节点是活动的(1)还是失败的(0)[在这种情况下,
    dict1
    的所有节点都是活动的]
    dict2
    包含连接到
    dict1
    的每个节点的所有节点
    dict3
    告诉我连接到
    dict1
    的每个节点的所有节点是否都处于活动状态(1)或出现故障(0)

    我的问题。我希望能够对节点之间的交互进行建模。这意味着,如果节点
    0
    处于活动状态(
    status=1
    ),并且有3个节点连接到该节点,如果所有节点都失败(
    status=0
    ),则节点
    0
    也会失败。如果只有一个连接的节点仍处于活动状态,则节点
    0
    也仍处于活动状态

    我的尝试。这是我设想的理论流程图,但我不知道如何将其转换为Python,也不知道这是否是最好的方法:

  • 通过dict1循环
  • 对于dict1的每个键,获取与dict1的当前键关联的dict2的值
  • 对于在dict2中找到的每个值,在dict3中检查它们的状态是0还是1(在dict2中找到的值成为dict3的键)
  • 如果(且仅当)以这种方式找到的所有dict3键均为0,则将与当前dict1键关联的值更改为0
  • PS:此流程图适用于10000个节点的网络,因此重点是速度。为循环嵌套3听起来可能是个(非常)坏的主意,所以我希望有一个不同的解决方案


    很抱歉,我没能把它转换成正确的代码,但我真的很挣扎。非常感谢

    正如JoshRomRock在评论中所建议的,您可以创建如下类:

    class Node(object):
        def __init__(self, node_id, neighbours, status):
            # neighbours could be a list of other Node objects
            self.node_id = node_id
            self.neighbours = neighbours
            self.status = status
    
        def neighbours_status(self):
            # this method would return a list of tuples, 
            # where first tuple elem is node_id and the second is its status
            return [(n.node_id, n.status) for n in self.neighbours]
    
     my_nodes = set()  # create set
     my_nodes.add(Node(0, [], 1))  # add a node with no neighbours
     # add some more nodes here ...
    
     for node in my_nodes:
         # do something with node.status, or node.node_id, or node.neighbours_status()
    
    然后在代码中使用它,如下所示:

    class Node(object):
        def __init__(self, node_id, neighbours, status):
            # neighbours could be a list of other Node objects
            self.node_id = node_id
            self.neighbours = neighbours
            self.status = status
    
        def neighbours_status(self):
            # this method would return a list of tuples, 
            # where first tuple elem is node_id and the second is its status
            return [(n.node_id, n.status) for n in self.neighbours]
    
     my_nodes = set()  # create set
     my_nodes.add(Node(0, [], 1))  # add a node with no neighbours
     # add some more nodes here ...
    
     for node in my_nodes:
         # do something with node.status, or node.node_id, or node.neighbours_status()
    
    我想这可能是个问题。我不相信您尝试实施解决方案的方式是最好的,但我将尝试回答您提出的问题。您可能会问另一个参数稍宽的问题

    以下是我认为您正在描述的伪代码:

    initialize nodes
    create some initial set_of_nodes such that all have status active.
    for node in set_of_nodes:
        if node has no neighbors:
            move on
        else:
            has_active_neighbor = False
            for neighbor in neighbors(node):
                add neighbor to set_of_nodes
                if neighbor's status is active:
                    has_active_neighbor = True
            if has_active_neighbor = False:
                node's status becomes inactive.
    
    此代码存在一些潜在问题。您可以在迭代过程中迭代并更改某些节点的状态,这意味着如果再次检查某些已处理的节点,它们将失败。所以你看到的是某种瀑布。您可能希望在节点之间循环,直到不发生任何更改。而且,在循环过程中添加到集合中有点奇怪。这在Python中是一个禁忌(一般来说)。因此,我正在创建一组新的节点,您正在添加这些节点。因此,根据您试图研究的系统规则,这可能不是最好的。另外,我不明白为什么你只从一个子集开始,而不是从整个网络开始

    下面是networkx的实现。我将循环使用它,直到没有变化发生

    import networkx as nx
    
    # code here to define graph, assign initial statuses, and create node_set
    # node attributes can be defined in several ways (one appears below)
    
    changes = True
    while changes:
        changes = False
        added_nodes = set()
        for x in node_set:
            if G.degree(x)==0 or G.node[x]['status'] == 'failed':
                continue  #nothing to see here, move on.
            else:
                has_active_neighbor=False
                for neighbor in G.neighbors(x):
                    added_nodes.add(neighbor) #put it here even if it is already in node_set
                    if G.node[neighbor]['status'] == 'active':
                        has_active_neighbor = True
                        break
                if not has_active_neighbor:
                    changes = True
                    G.node[x]['status'] = 'failed'
        if node_set.difference(added_nodes):  #True if any new nodes:
            node_set = node_set.union(added_nodes)
            changes = True
    
    #everything is done now - here's the dictionary of statuses:
    statuses = nx.get_node_attributes(G, 'status')
    

    您不必在3个DICT上循环,因为它们为您提供了对其值的直接访问。您只需要在dict1密钥集中进行迭代。但是你的主要问题是,你可以用一组对象做你想做的事情。谢谢!你能帮我做个“实验”吗?我发现字典里有很多可能的地雷……你有没有试着设置一个节点类,其中包含节点id、邻居(作为节点列表)和状态字段?将它们放在一个集合中,并对其进行迭代以应用您的规则。备注:我不了解NetworkX,因此我不确定您想要的输出。请忘记
    NetworkX
    ,我提到它只是想了解这个问题的来源。我真的不知道如何创建类,因为我对Python非常陌生。你能详细说明一下吗?如果你使用networkx,大部分都会自动处理。。。它将为您提供图形和所有节点。您可以指定任意节点属性。谢谢。顺便说一句,我不知道如何在我的情况下使用它。我不需要添加节点-我已经有10000个节点了。另外,您定义的
    my_nodes=set()
    是我从未见过的……为了使用类解决方案,您必须首先将节点的表示转换为该表示,然后您将受益于轻松迭代的能力。对于循环,它也比使用嵌套的
    更快。这就是我建议添加它们的原因。关于
    集合
    ,您可能想看看这里:几个问题:您将如何使用
    节点
    类?你怎么称呼它?类需要的
    对象是什么?它在三行中做了什么?对不起,这似乎很难理解…@pzelasko这和我昨天的意思很接近,谢谢。我没来得及把它写好。@Francesco Castellani我会尽力回答你们的问题。使用
    节点
    类时,应首先将这3个词典中的当前表示形式转换为
    节点
    对象的集合(或列表)。您可以以类似于我在第二个代码块的第二行中所做的方式创建
    节点
    对象。要使用其成员,只需编写
    Node.member
    ;请参阅我在答案中的最后一条评论。
    对象
    是节点类的父类,如果您想要一个“新样式”对象,则需要在Python2中指定该节点类(尽管这是一个与此问题无关的细节)。希望能有帮助。谢谢!我认为关于已经处理的节点的问题不是一个真正的问题。我