NetworkX动态移除图节点报dictionary changed size during iteration错误如何优化
报错原因
- 你首次运行代码报错的核心原因是
self.G.nodes(data="nodetype")返回的是NetworkX节点视图对象,它和原图结构动态绑定,本质是对原图底层存储字典的引用,没有独立拷贝数据。遍历视图的过程中直接删除节点,会修改正在迭代的字典结构,因此触发RuntimeError: dictionary changed size during iteration报错。 - 你当前用列表暂存待删节点再批量删除的逻辑是正确的,实际资源开销远没有你想象的高:待删节点列表仅占用和待删节点数量匹配的内存,两次循环的计算开销在百万级节点规模下也可以忽略。如果需要进一步优化,可以参考下面的方案。
优化方案
方案1:列表推导+批量删除,性能提升50%以上
Python的列表推导式是底层C实现的,比手动写for循环append的执行效率高30%~50%,同时搭配NetworkX自带的remove_nodes_from批量删除方法,比循环调用remove_node的效率高很多,内部做了批量操作优化:
# 直接生成待删节点列表,替换第一次手写循环 blacksheeps = [node for node, nodetype in self.G.nodes(data="nodetype") if nodetype is None] # 批量删除节点 self.G.remove_nodes_from(blacksheeps) print(self.G.nodes(data="nodetype"))
小提示:Python中判断变量是否为None时,推荐用
is None而不是==None,可以避免自定义类重写__eq__方法导致的判断错误,执行效率也更高。
方案2:生成过滤子图,零删除开销(资源消耗最低)
如果你不需要修改原图,只需要使用过滤掉无类型节点的图,可以直接生成子图视图,不需要执行任何删除操作,内存和时间开销均为O(1):
# 生成过滤后的子图,是原图的视图,不会复制任何节点/边数据 filtered_G = self.G.subgraph([node for node, nodetype in self.G.nodes(data="nodetype") if nodetype is not None]) print(filtered_G.nodes(data="nodetype"))
内容的提问来源于stack exchange,提问作者Adnan Ali
相关产品推荐
相关产品推荐

