自指词典理解
Self-referential dictionary comprehension
最近在回答一个问题。该代码按预期工作。但是我想看看我是否可以实现我很少使用的听写理解。首先,让我解释一下 .
OP 有一个示例列表,如 M1 = [['a', 14], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
。
他们想要类似这样的输出。 [['a',14,7,16],['b',3,15],['c',22,1,5]]
。有道理,所以我创建了一个答案。
原码
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
for lsts in x:
if lsts[0] in dictX.keys():dictX[lsts[0]].extend(lsts[1:])
else:dictX[lsts[0]] = lsts[1:]
输出
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
我会的
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x}
错误
Traceback (most recent call last):
File "/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py", line 3, in
dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x}
File "/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py", line 3, in
dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x}
KeyError: 'a'
我的观点在很多方面似乎都是错误的。我将其用作 reference(已接受答案的最高评论)
{(a if condition else b): value for key, value in dict.items()}
有什么方法可以将其转化为听写理解。
我想要一个与我提供的参考和我在原始代码
中使用的逻辑相一致的例子
由于嵌套循环,一点也不快,但它是可行的。在字典理解中使用列表理解。
seq = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
res = {i[0]:[k for j in seq if j[0] == i[0] for k in j[1:]] for i in seq}
print(res)
输出
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
PS :我意识到这个问题与 Is it possible to access current object while doing list/dict comprehension in Python? 更相关,如果有人认为这是一个骗局,请将其标记为这样,我不确定,所以我将保留它。
通常您无法在理解中引用字典本身,因为在理解完成之前不会将名称分配给生成的字典,因此您必须满足于预定义dictionary* 并利用现有字典的变异方法。
由于您正在遍历输入列表,因此无论何时遇到键,您都需要使用新值更新现有字典。由于您不能在字典理解中使用赋值,因此您需要使用 dict.update()
方法(或 __setitem__
或 setdefault
)。该方法总是 returns None
,因此您可以利用它在字典理解中的许多不同位置实现所需的副作用。
特别是,任何过滤条件子句都会被执行,所以你可以使用它。或者,expr or value
将计算表达式,它总是 return None
,并且由于这是错误的,整个表达式的计算结果为 value
,因此您可以将该表达式放在键中或价值。这给了我们以下可能性:
过滤器子句中的副作用:
d = {}
d = {k: d[k] for k, *vals in x if d.update({k: d.get(k, []) + vals}) is None}
expr or key
表达式中的副作用:
d = {}
d = {d.update({k: d.get(k, []) + vals}) or k: d[k] for k, *vals in x}
expr or value
表达式中的副作用:
d = {}
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for k, *vals in x}
* 使用赋值表达式 (Python 3.8+),你可以用这个可憎的东西在推导本身内部预定义字典:
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for i, (k, *vals) in enumerate(x) if i or not (d := {})}
这使用 enumerate()
来检测您何时处于第一次迭代,在这种情况下,赋值表达式可以构造在其余理解中使用的字典。第一次迭代后,赋值表达式不会再次求值,因此 d
不会在求值过程中被重新赋值。
注意:显然,所有 这个答案中显示的方法都很糟糕。推导式中的副作用是不必要的、出乎意料的、令人困惑的,总之,是愚蠢的。不要使用此代码。但是看到什么是可能的很有趣!
最近在回答一个问题。该代码按预期工作。但是我想看看我是否可以实现我很少使用的听写理解。首先,让我解释一下
OP 有一个示例列表,如 M1 = [['a', 14], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
。
他们想要类似这样的输出。 [['a',14,7,16],['b',3,15],['c',22,1,5]]
。有道理,所以我创建了一个答案。
原码
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
for lsts in x:
if lsts[0] in dictX.keys():dictX[lsts[0]].extend(lsts[1:])
else:dictX[lsts[0]] = lsts[1:]
输出
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
我会的
x = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
dictX = {}
dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x}
错误
Traceback (most recent call last): File "/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py", line 3, in dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x} File "/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py", line 3, in dictX ={(dictX[lsts[0]].extend(lsts[1:]) if lsts[0] in dictX.keys() else dictX[lsts[0]]): lsts[1:] for lsts in x} KeyError: 'a'
我的观点在很多方面似乎都是错误的。我将其用作 reference(已接受答案的最高评论)
{(a if condition else b): value for key, value in dict.items()}
有什么方法可以将其转化为听写理解。 我想要一个与我提供的参考和我在原始代码
中使用的逻辑相一致的例子由于嵌套循环,一点也不快,但它是可行的。在字典理解中使用列表理解。
seq = [['a', 14,15], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]]
res = {i[0]:[k for j in seq if j[0] == i[0] for k in j[1:]] for i in seq}
print(res)
输出
{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}
PS :我意识到这个问题与 Is it possible to access current object while doing list/dict comprehension in Python? 更相关,如果有人认为这是一个骗局,请将其标记为这样,我不确定,所以我将保留它。
通常您无法在理解中引用字典本身,因为在理解完成之前不会将名称分配给生成的字典,因此您必须满足于预定义dictionary* 并利用现有字典的变异方法。
由于您正在遍历输入列表,因此无论何时遇到键,您都需要使用新值更新现有字典。由于您不能在字典理解中使用赋值,因此您需要使用 dict.update()
方法(或 __setitem__
或 setdefault
)。该方法总是 returns None
,因此您可以利用它在字典理解中的许多不同位置实现所需的副作用。
特别是,任何过滤条件子句都会被执行,所以你可以使用它。或者,expr or value
将计算表达式,它总是 return None
,并且由于这是错误的,整个表达式的计算结果为 value
,因此您可以将该表达式放在键中或价值。这给了我们以下可能性:
过滤器子句中的副作用:
d = {}
d = {k: d[k] for k, *vals in x if d.update({k: d.get(k, []) + vals}) is None}
expr or key
表达式中的副作用:
d = {}
d = {d.update({k: d.get(k, []) + vals}) or k: d[k] for k, *vals in x}
expr or value
表达式中的副作用:
d = {}
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for k, *vals in x}
* 使用赋值表达式 (Python 3.8+),你可以用这个可憎的东西在推导本身内部预定义字典:
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for i, (k, *vals) in enumerate(x) if i or not (d := {})}
这使用 enumerate()
来检测您何时处于第一次迭代,在这种情况下,赋值表达式可以构造在其余理解中使用的字典。第一次迭代后,赋值表达式不会再次求值,因此 d
不会在求值过程中被重新赋值。
注意:显然,所有 这个答案中显示的方法都很糟糕。推导式中的副作用是不必要的、出乎意料的、令人困惑的,总之,是愚蠢的。不要使用此代码。但是看到什么是可能的很有趣!