代码之家  ›  专栏  ›  技术社区  ›  Buddy Bob Youngkhaf

用append/extend理解if/else

  •  0
  • Buddy Bob Youngkhaf  · 技术社区  · 3 年前

    最近,我在回答一个问题。代码按预期工作。但我想看看我是否能实现我很少使用的字典理解。首先,让我解释一下 problem .

    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}
    

    错误

    追溯(最后一次通话): 文件“/Users/aspra/Documents/Python/Py_Programs/data/timeComplexity/test.Py”,第3行,in dictX={(dictX[lsts[0]].extend(lsts[1:])如果dictX.keys()中的lsts[0],否则dictX[lists[0]]):lsts[1:]对于x中的lsts} 文件“/Users/aspra/Documents/Python/Py_Programs/data/timeComplexity/test.Py”,第3行,in dictX={(dictX[lsts[0]].extend(lsts[1:])如果dictX.keys()中的lsts[0],否则dictX[lists[0]]):lsts[1:]对于x中的lsts} 密钥错误:“a”

    我在这方面的尝试似乎在很多方面都是错误的。我用这个作为 reference (已接受答案的最高评价)

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

    有什么方法可以把这转化为字典理解吗。 我想要一个例子,它符合我提供的参考文献和我在我的文章中使用的逻辑 原始代码

    1 回复  |  直到 3 年前
        1
  •  3
  •   python_user    3 年前

    由于嵌套循环,速度一点也不快,但这是可行的。在字典理解中使用列表理解。

    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? ,如果有人觉得这是一个骗局,请务必标记出来,我不确定,所以我就这样算了。

        2
  •  1
  •   alkasm Anuj Gautam    3 年前

    一般来说,你无法在理解中引用词典本身,因为在理解完成之前,名称不会被分配给生成的词典,所以你必须满足于预定义词典*并利用现有词典的变异方法。

    由于您正在迭代输入列表,因此每当遇到键时,都需要用新值更新现有字典。由于你不能在词典理解中使用作业,你会想使用 dict.update() 方法(或 __setitem__ setdefault ). 该方法总是返回 None ,因此您可以利用它在词典理解中的许多不同地方实现所需的副作用。

    特别是,任何过滤条件子句都将被执行,因此您可以使用它。或者, expr or value 将计算表达式,该表达式将始终返回 没有 ,因为这是假的,所以整个表达式的计算结果为 value ,因此您可以将该表达式放置在键或值中。这为我们提供了以下可能性:

    在filter子句中有副作用:

    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或值 表达式:

    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 在评估过程中不会被重新分配。


    注:显然, 全部的 这个答案中显示的方法有很多都很糟糕。理解中的副作用是不必要的、出乎意料的、令人困惑的,总之是愚蠢的。不要使用此代码。但看看有什么可能是很有趣的!