使用列表推导和dict进行正则表达式替换

时间:2016-01-04 14:29:02

标签: python regex python-3.x dictionary list-comprehension

以下Python 3代码循环遍历字符串列表,并使用正则表达式替换每个字符串中的一些文本。

这里的字符串很简单,但在实际情况下它们可能更复杂,数量更多,因此我决定使用re.sub()而不是str.replace()

all = ("this line has no hits",
       "a letter to tom from peter",
       "today bonny went to school",
       "harry made some cake")

for myitem in all:
    newitem = re.sub("harry","sally",myitem)
    newitem = re.sub("tom","jerry",newitem)
    newitem = re.sub("bonny","clyde",newitem)
    print(newitem)

这似乎按预期工作:

>>> this line has no hits
a letter to jerry from peter
today clyde went to school
sally made some cake
>>> 

在现实生活中会有大量的字符串,这会造成一堆乱码。我认为通过在dict中定义正则表达式对并使用列表理解,可能有更简洁,更Pythonic的方法。所以我尝试了这个:

mydict = {'harry':'sally','tom':'jerry','bonny':'clyde'}

newall = [re.sub(i, mydict[i], j) for i in mydict for j in all]
print(newall)

这不起作用,因为它没有返回带有替换文字的字符串列表,但我不明白它为什么不起作用。

我的问题是:

  • 我在上面的例子中做错了什么?
  • 有没有更好的方法来解决涉及长字符串的大量替换问题?

(注意我可能已经错过了这里显而易见的事情,因为我只看了几天Python;我的背景是R和Perl。)

2 个答案:

答案 0 :(得分:5)

有两个列表的列表理解是令人讨厌的。它们容易出错并且难以阅读。为什么不简单地使用两个循环?:

all = ("this line has no hits",
       "a letter to tom from peter",
       "today bonny went to school",
       "harry made some cake")

mydict = {'harry':'sally','tom':'jerry','bonny':'clyde'}

output = []
for line in all:
    for search, replace in mydict.items():
        line = re.sub(search, replace, line)
    output.append(line)

print(output)
  

['这条线没有点击','来自彼得的一封致杰里的信,'今天克莱德去了学校',' sally made一些蛋糕']

答案 1 :(得分:0)

您需要使用另一个函数式编程概念,reduce。

您希望将mydict中的每个键值一个接一个地应用于相同的字符串,从而生成一个最终字符串。在这种情况下(使用多值dict / list / set获取单个答案),您使用reduce。像这样:

import re

# copied from question
all = ("this line has no hits",
       "a letter to tom from peter",
       "today bonny went to school",
       "harry made some cake")

mydict = {'harry':'sally','tom':'jerry','bonny':'clyde'}

# define the function used in reduce
def replace_strings(line, mydictkey):
    return re.sub(mydictkey, mydict[mydictkey], line)

for line in all:
    print reduce(replace_strings, mydict.keys(), line)

以列表理解形式:

newall = [reduce(replace_strings, mydict.keys(), line) for line in all]
print newall

函数式编程结构有一些很好的基础知识(简化,列表理解,过滤):https://docs.python.org/2/tutorial/datastructures.html#functional-programming-tools