简体   繁体   English

自指字典理解

[英]Self-referential dictionary comprehension

Recently, I was answering a question.最近,我在回答一个问题。 The code worked as intended.代码按预期工作。 But I wanted to see if I could implement dict comprehension which I rarely use.但我想看看我是否可以实现我很少使用的字典理解。 First of all, let me explain the problem .首先,让我解释一下这个问题

The OP had an example list like M1 = [['a', 14], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]] . OP 有一个示例列表,例如M1 = [['a', 14], ['a',7], ['a',16],['b',3],['b',15],['c',22],['c',1],['c',5]] They wanted an output similar to this.他们想要一个与此类似的 output。 [['a',14,7,16],['b',3,15],['c',22,1,5]] . [['a',14,7,16],['b',3,15],['c',22,1,5]] Makes sense, so I created an answer.有道理,所以我创建了一个答案。


original code原始代码

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:]  

output output

{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}

my go at this我的 go 在这个

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}

Error错误

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' Traceback(最近一次调用最后):文件“/Users/aspera/Documents/Python/Py_Programs/data/timeComplexity/test.py”,第 3 行,在 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",第 3 行,在 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'

My shot at this seems wrong in so many ways.我对此的看法在很多方面似乎都是错误的。 I used this as a reference (top comment of accepted answer)我将此用作参考(已接受答案的最高评论)

{(a if condition else b): value for key, value in dict.items()}

Is there any way I could turn this to dict comprehension.有什么办法可以把它变成听写理解。 I'd like an example which goes along the lines of the reference I provided and the logic I have used in my original code我想要一个示例,它与我提供的参考和我在原始代码中使用的逻辑一致

Not at all faster due to nested loops, but it is doable.由于嵌套循环,速度一点也不快,但它是可行的。 Using list comprehension inside dict comprehension.在 dict 理解中使用列表理解。

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)

Output Output

{'a': [14, 15, 7, 16], 'b': [3, 15], 'c': [22, 1, 5]}

PS: I realize this question is more related to Is it possible to access current object while doing list/dict comprehension in Python? PS:我意识到这个问题与在Python 中进行列表/字典理解时是否可以访问当前 object 更相关? , if anyone feels that is a dupe do mark it as such, I am not sure so I am leaving it be. ,如果有人认为这是一个骗子,请务必将其标记为这样,我不确定,所以我将其保留。

In general you won't be able to reference the dictionary itself in the comprehension, because the name won't get assigned to the resulting dictionary until the comprehension is completed, so you'll have to settle for predefining the dictionary* and utilize mutating methods of the existing dictionary.通常,您将无法在推导中引用字典本身,因为在推导完成之前,名称不会分配给结果字典,因此您必须满足于预定义字典*并利用 mutating现有字典的方法。

Since you're iterating over the input list, you'll need to update the existing dictionary with the new values whenever you come across the key.由于您正在遍历输入列表,因此无论何时遇到该键,您都需要使用新值更新现有字典。 And as you can't use an assignment in the dictionary comprehension, you'll want to use the dict.update() method (or __setitem__ or setdefault ).由于您不能在字典理解中使用赋值,因此您需要使用dict.update()方法(或__setitem__setdefault )。 That method always returns None , so you can utilize that to achieve the desired side effect in a number of different places inside the dictionary comprehension.该方法始终返回None ,因此您可以利用它在字典理解中的许多不同位置实现所需的副作用。

In particular, any filtering condition clause will be executed, so you can use that.特别是,将执行任何过滤条件子句,因此您可以使用它。 Alternatively, expr or value will evaluate the expression, which will always return None , and since that's falsey the whole expression evaluates to value , so you can place that expression in the key or value.或者, expr or value将评估表达式,该表达式将始终返回None ,并且由于这是错误的,整个表达式的计算结果为value ,因此您可以将该表达式放在键或值中。 That gives us the following possibilities:这给了我们以下可能性:

With the side effect in the filter clause:过滤子句中的副作用:

d = {}
d = {k: d[k] for k, *vals in x if d.update({k: d.get(k, []) + vals}) is None}

With the side effect in a expr or key expression:expr or key表达式中具有副作用:

d = {}
d = {d.update({k: d.get(k, []) + vals}) or k: d[k] for k, *vals in x}

With the side effect in a expr or value expression:expr or value表达式中具有副作用:

d = {}
d = {k: d.update({k: d.get(k, []) + vals}) or d[k] for k, *vals in x}

* Using assignment expressions (Python 3.8+), you can predefine the dictionary inside the comprehension itself with this abomination: * 使用赋值表达式(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 := {})}

This uses enumerate() to detect when you're on the first iteration, in which case an assignment expression can construct the dictionary that is used in the rest of the comprehension.这使用enumerate()来检测您何时进行第一次迭代,在这种情况下,赋值表达式可以构造在理解的 rest 中使用的字典。 After the first iteration, the assignment expression is not evaluated again so d doesn't get reassigned in the course of the evaluation.在第一次迭代之后,赋值表达式不再被计算,因此d在计算过程中不会被重新赋值。


Note: Obviously, all of the methods shown in this answer are terrible.注意:显然,此答案中显示的所有方法都很糟糕。 Side-effects inside comprehensions are unnecessary, unexpected, confusing, and in one word, silly.理解中的副作用是不必要的、出乎意料的、令人困惑的,总而言之,是愚蠢的。 Do not use this code.不要使用此代码。 But it is fun to see what's possible!但看到什么是可能的很有趣!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM