如何将含正则替换的双层for循环改写为Python列表推导式?
问题:把双层循环的正则替换代码改成列表推导式
原代码的逻辑是读文件里的每一行,对每行依次用patterns字典里的所有规则做正则替换(每次替换都会更新当前行内容),最后把处理好的行加到targetList里:
with open(sourceFile, 'r+t') as file: for line in file: for key, value in patterns.items(): line = re.compile(value, flags=re.IGNORECASE).sub(key, line) targetList.append(line)
你写的示例列表推导式会生成每行对应所有替换操作后的多个结果(一行对应一个子列表,子列表里是每次替换后的内容),这和原代码的累积替换逻辑不一样。正确的改写要实现对每行的累积替换,用functools.reduce就能做到:
正确改写方案
先导入functools和re模块,再用列表推导式结合reduce实现:
import re from functools import reduce with open(sourceFile, 'r+t') as file: targetList = [ reduce( lambda current_line, kv: re.compile(kv[1], flags=re.IGNORECASE).sub(kv[0], current_line), patterns.items(), line ) for line in file ]
说明
reduce会把patterns.items()里的每个键值对依次作用到初始的line上,每次替换后的结果作为下一次替换的输入,和原代码里逐次修改line的逻辑完全一致。- 列表推导式遍历文件的每一行,对每行执行上述累积替换,最终生成的列表和原代码的
targetList结果完全相同。
要是不想用functools.reduce,也可以用嵌套生成器表达式模拟累积替换,但这种写法可读性差,不太推荐:
import re with open(sourceFile, 'r+t') as file: targetList = [ next( updated_line for updated_line in [line] for key, value in patterns.items() for updated_line in [re.compile(value, flags=re.IGNORECASE).sub(key, updated_line)] ) for line in file ]
内容的提问来源于stack exchange,提问作者ludovico
相关产品推荐
相关产品推荐

