多级列表理解中是否需要中间列表
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
次迭代。剩下的就简单了。
这里有一个具体的例子:
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
次迭代。剩下的就简单了。