我正在尝试编写一个函数进程(s,d),用字典替换字符串中的缩写。其中s是字符串输入,d是字典。例如:
>>>d = {'ASAP':'as soon as possible'}
>>>s = "I will do this ASAP. Regards, X"
>>>process(s,d)
>>>"I will do this as soon as possible. Regards, X"
我尝试使用split函数分隔字符串并将每个部分与字典进行比较。
def process(s):
return ''.join(d[ch] if ch in d else ch for ch in s)
但是,它会返回相同的字符串。我怀疑代码不起作用,因为ASAP在原始字符串中完全停止。如果是这样,我如何忽略标点符号并获得ASAP替换?
答案 0 :(得分:5)
以下是使用单个正则表达式执行此操作的方法:
In [24]: d = {'ASAP':'as soon as possible', 'AFAIK': 'as far as I know'}
In [25]: s = 'I will do this ASAP, AFAIK. Regards, X'
In [26]: re.sub(r'\b' + '|'.join(d.keys()) + r'\b', lambda m: d[m.group(0)], s)
Out[26]: 'I will do this as soon as possible, as far as I know. Regards, X'
与基于str.replace()
的版本不同,它会观察单词边界,因此不会替换碰巧出现在其他单词中间的缩写(例如“fetch”中的“etc”)。
此外,与目前为止提供的大多数(全部?)其他解决方案不同,它只对输入字符串进行一次迭代,无论字典中有多少搜索字词。
答案 1 :(得分:2)
您可以这样做:
def process(s,d):
for key in d:
s = s.replace(key,d[key])
return s
答案 2 :(得分:2)
以下是一个有效的解决方案:使用re.split(),并按字边界分割(保留插页式字符):
''.join( d.get( word, word ) for word in re.split( '(\W+)', s ) )
此代码与Vaughn或Sheena的答案有一个显着不同之处在于此代码利用了字典的O(1)查找时间,而他们的解决方案则查看字典中的每个键。这意味着当s
很短并且d
非常大时,他们的代码运行时间会更长。此外,部分单词仍将在其解决方案中被替换:如果d = { "lol": "laugh out loud" }
和s="lollipop"
他们的解决方案将错误地生成"laugh out loudlipop"
。
答案 3 :(得分:1)
使用正则表达式:
re.sub(pattern,replacement,s)
在您的申请中:
ret = s
for key in d:
ret = re.sub(r'\b'+key+r'\b',d[key],ret)
return ret
\ b匹配单词的开头或结尾。感谢Paul的评论
答案 4 :(得分:0)
不使用空格分割,而是使用:
split("\W")
它将被任何不属于单词的角色的任何东西分开。
答案 5 :(得分:0)
这也是字符串替换(+1到@VaughnCato)。这使用reduce
函数迭代您的字典,用值替换字符串中键的任何实例。 s
在这种情况下是累加器,它在每次迭代时被减少(即被馈送到替换函数),维持所有过去的替换(同样,根据@PaulMcGuire的上述点,这将替换从最长的开始到结束的键。最短的。)
In [1]: d = {'ASAP':'as soon as possible', 'AFAIK': 'as far as I know'}
In [2]: s = 'I will do this ASAP, AFAIK. Regards, X'
In [3]: reduce(lambda x, y: x.replace(y, d[y]), sorted(d, key=lambda i: len(i), reverse=True), s)
Out[3]: 'I will do this as soon as possible, as far as I know. Regards, X'
至于为什么你的函数没有返回你期望的东西 - 当你遍历s
时,你实际上是在迭代字符串的字符 - 而不是单词。您可以通过迭代s.split()
(这将是单词列表)来调整您的版本,但是您会遇到标点符号导致单词与您的字典不匹配的问题。您可以通过导入string
并从每个单词中删除string.punctuation
来匹配它,但这会从最终字符串中删除标点符号(因此,如果替换不是正则,那么正则表达式可能是最佳选项工作)。
答案 6 :(得分:0)
python 3.2
[s.replace(i,v) for i,v in d.items()]