多级列表理解中是否需要中间列表

Is an intermediate list necessary in a multi-level list comprehension

这里有一个具体的例子:

my_dict={k:int(encoded_value) 
         for (k,encoded_value) in 
             [encoded_key_value.split('=') for encoded_key_value in 
              many_encoded_key_values.split(',')]}

问题是关于内部列表[],是否可以避免,例如:

# This will not parse
my_dict={k:int(encoded_value) 
         for (k,encoded_value) in 
             encoded_key_value.split('=') for encoded_key_value in 
             many_encoded_key_values.split(',')}

...,这是无效语法:

NameError: name 'encoded_key_value' is not defined

示例数据:aa=1,bb=2,cc=3,dd=4,ee=-5

您可以通过使用中间生成器表达式来避免创建中间列表:

my_dict={k:int(encoded_value)
         for (k,encoded_value) in
             (encoded_key_value.split('=') for encoded_key_value in
              many_encoded_key_values.split(','))}

语法方面这几乎是一样的;不是先生成中间列表然后使用元素,而是即时使用元素。


让这个过于冗长你可以使用一个 'data pipeline' 由生成器组成:

eq_statements = (item.strip() for item in many_encoded_key_values.split(','))
var_i = (var_i.split('=') for var_i in eq_statements)
my_dict = {var: int(i) for var, i in var_i}
print(my_dict)

(不幸的是 .split 不是 return 生成器,因此考虑保存 space 这没有多大用处......对于处理大文件这样的事情可能会派上用场。 )

找到 this answer,其中 split 作为迭代器。以防万一...

如前所述,生成器表达式将增强您避免创建内部列表的方法。但是有一个更短的方法来获得所需的结果,使用 re.findall() 函数:

result = {k:int(v) for k,v in re.findall(r'(\w+)=([^,]+)', many_encoded_key_values)}
print(result)

输出:

{'dd': 4, 'aa': 1, 'bb': 2, 'ee': -5, 'cc': 3}

另一种方法是使用 re.finditer() 函数,其中 returns 'callable_iterator' 实例:

result = {m.group(1):int(m.group(2)) for m in re.finditer(r'(\w+)=([^,]+)', many_encoded_key_values)}

FWIW,这是一个实用的方法:

def convert(s):
    k, v = s.split('=')
    return k, int(v)

d = dict(map(convert, data.split(',')))
print(d)

输出

{'aa': '1', 'bb': '2', 'cc': '3', 'dd': '4', 'ee': '-5'}

一个简单紧凑的变体,非常接近您最初的尝试:

d = {v.strip(): int(i) for s in data.split(',') for v, i in (s.split('='),)}

唯一额外的 'trick' 是将 s.split('=') 包裹在一个元组中(用圆括号将其包围:(s.split('='),)),以便获得 split 的两个元素相同的 for 次迭代。剩下的就简单了。