我试图写一个函数过程(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"
我已经使用分割功能分割字符串和比较字典中的每个部分尝试。
def process(s):
return ''.join(d[ch] if ch in d else ch for ch in s)
但是,它返回我完全相同的字符串。 我有一个怀疑,代码没有在原来的字符串,因为句号的作品背后尽快。 如果是这样,我怎么忽略了标点符号,并得到尽快更换?
这里有一个方法与单个正则表达式来做到这一点:
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()
这个观察单词边界,因此不会取代碰巧出现在其他字(“取”,例如“等”),中间的缩写。
此外,与大多数(全部?)其他迄今提出的解决方案,它遍历输入字符串只有一次,不管有多少搜索词中有字典。
你可以这样做:
def process(s,d):
for key in d:
s = s.replace(key,d[key])
return s
这里是一个可行的解决方案:使用re.split() ,和分割由字边界(保留间质性字符):
''.join( d.get( word, word ) for word in re.split( '(\W+)', s ) )
一个显著的差异,该代码具有从沃恩的或希娜的回答是,这个代码利用O(1)词典的查找时间的优势,而他们的解决方案看字典中的每一个关键。 这意味着,当s
短, d
是非常大的,他们的代码将显著需要更长的时间来运行。 此外,字的部分仍然会在他们的解决方案替换为:如果d = { "lol": "laugh out loud" }
和s="lollipop"
他们的解决方案将错误地产生"laugh out loudlipop"
。
使用正则表达式:
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词的开头或结尾匹配。 感谢保罗的评论
python 3.2
[s.replace(i,v) for i,v in d.items()]
这是字符串替换,以及(+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
从每一个字,但会从最终的字符串删除标点符号(所以正则表达式将可能是最好的选择,如果更换不工作)。