【问题标题】:Failure converting complex code to a list comprehension将复杂代码转换为列表理解失败
【发布时间】:2020-04-25 11:54:18
【问题描述】:

注意:建议的答案都不适合我,因为它们是 for-loop 驱动的(我已经在工作了)并且不解释列表理解版本有什么问题。


我正在尝试转变

('name:80', 'desc:100')

进入

{'name': 80, 'desc': 100}

一个工作的for-loop:

new_wrap = {}
for item in wrap:
    k, v = item.split(':')
    new_wrap[k] = int(v)
wrap = new_wrap

一个非工作列表理解:

wrap = dict([
    (k, int(v))
    for item in wrap
    for (k, v) in item.split(':')
    ])

给了

Traceback (most recent call last):
  File ..., line ..., in ...
    for (k, v) in item.split(':')
ValueError: too many values to unpack

我做错了什么?

【问题讨论】:

标签: python list-comprehension


【解决方案1】:

我找到了这个解决方案:

x = ('name:80', 'desc:100') dict([tuple(a.split(':')) for a in x])

【讨论】:

  • 这不会将字符串"80" 转换为数字80。
  • 更改第二行:dict([tuple([a.split(':')[0], int(a.split(':')[1])]) for a in x ])
【解决方案2】:

借助 John Kugelman 提供的见解,我能够找出问题所在并找到我想要的解决方案。


for 循环的工作代码:

k, v = item.split(':')

细分:

  • item.split(':') == 'name:80'.split(':') == 'name', '80'
  • k, v = 'name', '80'
  • k == 'name' and v == 80

list-comp中的非工作代码:

for (k, v) in item.split(':')

细分:

  • item.split(':') == 'name:80'.split(':') == 'name', '80'
  • for (k, v) in ('name', '80')

还有一个问题:in 不一样 =。 in 迭代它的参数,一次返回一个,所以:

  • k, v = 'n', 'a', 'm', 'e' 是尝试的内容,因为试图将四个项目塞入两个我们得到ValueError: too many values to unpack 异常。

简单的解决方案是将item.split()封装成一个自己的元组:

  • for k, v in (item.split(':'), )

变成了

  • for k, v in (('name', '80'), )

由于元组中的第一项是我们得到的元组

  • k, v = 'name', '80' 用于第二个 for 循环的第一次(也是唯一一次)迭代

问题得到解决,无需在主list-comp 内嵌套另一个list-comp。

决赛,工作中list-comp:

    [
    (k, int(v))
    for item in wrap
    for (k, v) in (item.split(':'), )
    ]

【讨论】:

  • 无论出于何种原因您必须坚持您的列表理解,但与@John Kugelman 的答案中提供的 dict 理解相比,这是不可读和丑陋的。恕我直言,这应该是公认的答案。
  • @Jeronimo:list-comp 显示在最后,因为那是问题所在,我可以在这里展示解决方案。实际使用的代码确实使用了 John Kugelman 概述的 dict/generator 方法。约翰得到了赏金,因为他的回答解释了我做错了什么;这是公认的答案,因为它详细说明出了什么问题,为什么,并且有一个不会将一个理解嵌套在另一个理解中的解决方案。
【解决方案3】:

如果您想坚持一级深度的理解并且不介意使用 Python 3.8+,您可以使用赋值表达式将拆分结果保存在变量中以进行索引:

{(t := s.split(':'))[0]: int(t[1]) for s in wrap}

【讨论】:

  • 这很酷,但我不想在生产代码中看到它! ;-)
【解决方案4】:

你不想迭代item.split(':'),你想解包它。为此,您可以引入嵌套推导式或生成器表达式。这让您有机会创建新变量 k 和 v:

dict([
    (k, int(v))
    for k,v in (item.split(':') for item in wrap)
    ])

然后我会去掉方括号。使用动态生成条目的生成器表达式而不是在内存中构建整个列表并在创建字典时将其丢弃的列表推导效率更高。

dict((k, int(v))
     for k,v in (item.split(':') for item in wrap))

您可以通过使用带有花括号的 dict 推导进一步简化它:

{k: int(v) for k,v in (item.split(':') for item in wrap)}

【讨论】:

    【解决方案5】:

    您应该将拆分与转换为 int 分开:

    {k: int(v) for k, v in [w.split(":") for w in wrap]}
    #{'name': 80, 'desc': 100}
    

    但是,正如 roganjosh 正确建议的那样,您不会从中获益。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-12
      • 2020-01-26
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多