python - 将列表的定义从迭代转换为理解
问题描述
我有一个采用边缘列表的方法,边缘具有这种形式:(v1,v2,capacity)
并返回这种形式的字典:
dico = {v1:{v2:capacity,v3:capacity} v2:...}
这dico
代表一个图表
我想通过理解的方式定义这个 dico,但我真的被阻止了,我什至不确定我们能做到这一点,所以有人可以告诉我是否可能吗?这是我的功能:
def _init_from_edges(self, edges):
self._G={}
for e in edges:
if e[0] in self._G:
self._G[e[0]][e[1]]=e[2]
else:
self._G[e[0]]={e[1]:e[2]}
解决方案
您的代码不能轻易利用dict
理解,因为它实际上是一个 multidict(其中一个键没有一个值,而是多个值)。
您可以使用collections.defaultdict
以下方法简化代码:
from collections import defaultdict
def _init_from_edges(self, edges):
self._G = defaultdict(dict)
for v1, v2, capacity in edges:
self._G[v1][v2] = capacity
# Optional: Remove defaultdict behaviors after building
self._G = dict(self._G)
使用defaultdict(dict)
意味着当一个键不在字典中时,它会立即用一个全新的来创建dict
,所以你根本不需要执行成员资格测试。
请注意,我还使用了对命名变量的解包而不是重复索引,以使代码更具自我记录性。
使这项工作具有实际dict
理解的唯一方法是:
- 为每个输入重新扫描
edges
一次以收集给定的所有v2
/capacity
对v1
(但那是O(n**2)
,所以如果edges
可以很大,那是个坏主意) - 提前将每个值的所有值打包
v1
在一起,以便dict
可以一次构建每个子项。
由于选项#1通常非常浪费,因此作为dict
理解而不edges
一遍又一遍地重新扫描的唯一实用方法是选项#2,您可以在O(n log n)
排序后itertools.groupby
执行以下操作:
from itertools import groupby
from operator import itemgetter
def _init_from_edges(self, edges):
self._G = {v1: {v2: capacity for _, v2, capacity in grp}
for v1, grp in groupby(sorted(edges, key=itemgetter(0)),
key=itemgetter(0))}
这需要O(n log n)
对工作进行排序edges
(如果edges
已经排序,Python 的 TimSort 意味着它更接近O(n)
工作),然后O(n)
对结果进行分组。比 快{v1: {v2: capacity for v, v2, capacity in edges if v == v1} for v1, _, _ in edges}
,但仍然比不理解的方法慢defaultdict
(O(n)
在所有情况下)。
推荐阅读
- php - 如何修复在 leven 主题中拒绝导入的演示内容?
- android - ADB shell 命令在 Android TV 上的 YouTube 应用中设置媒体播放位置
- kotlin - 为什么在运行以下代码时我没有收到带有消息“请不要为空”的运行时异常
- python - 在 python 中编码斐波那契。出现错误
- lua - roblox 上的水下相机效果
- r - 我无法使用 siber 包在椭圆图的点上绘制颜色
- node.js - 即使正确传递数据,AdonisJS Validator 也会抛出错误
- lua - 试图以不同的速率和位置生成球(roblox)
- java - 代码是如何分配到四个核心中的,以及如何指出哪个核心最快可以达到解决方案,哪个核心最长?
- batch-file - 通过批处理文件启用 Chrome 控制台日志参数