2010-10-07 127 views
12

我想用单个实例"*"替换字符串中的"*"字符的重复实例。例如,如果字符串是"***abc**de*fg******h",我希望它被转换为"*abc*de*fg*h"如何使用python中的该字符的单个实例替换字符的重复实例

我很新的Python(和一般的编程),并试图用像正则表达式和与string.replace():

import re  
pattern = "***abc**de*fg******h" 
pattern.replace("*"\*, "*") 

其中\*应该替换的所有实例“* “性格。但是我得到了:SyntaxError:行后续字符的意外字符。

我也试图与一个操纵它像循环:

def convertString(pattern): 
for i in range(len(pattern)-1): 
    if(pattern[i] == pattern[i+1]): 
     pattern2 = pattern[i] 
return pattern2 

但是这其中只打印“*”,因为式样2 =模式[I]不断重新定义模式2是什么错误?

任何帮助,将不胜感激。

回答

4

我建议使用re module子功能:

import re 

result = re.sub("\*+", "*", "***abc**de*fg******h") 

我强烈建议通过有关重新和好的做法的文章阅读。如果你不熟悉它们,它们可能会很棘手。实际上,使用原始字符串是一个好主意。

+0

非常感谢你,这很好,我将阅读关于RE的文章,弄清楚代码的“\ +”部分到底发生了什么。我不知道你可以结合使用多个符号。我以为你只能用“+”或“*”为例。 – NSchrading 2010-10-07 04:17:11

+2

@NSchrading:在''\\ * +“'中,我逃避了*字符,因为它是一个特殊的re符号。所以我匹配一个字面*字符,+表示一个或多个。 – JoshD 2010-10-07 04:20:13

0
re.sub('\*+', '*', pattern) 

这样做。

1

明智的正则表达式我会尽量按照JoshD的建议。但这里有一个改进。

使用 -

regex = re.compile('\*+') 
result = re.sub(regex, "*", string) 

这将从根本上缓存你的正则表达式。因此,在循环中后续的使用会让你的正则表达式操作更快。

+1

这是一个不成熟的优化。无论如何,Python会缓存最近使用过的编译过的正则表达式。 – kindall 2010-10-07 04:54:04

0

没有正则表达式,你可以使用与“*”检查一般重复元素移除:

source = "***abc**dee*fg******h" 
target = ''.join(c for c,n in zip(source, source[1:]+' ') if c+n != '**') 
print target 
4

如何对非正则表达式的方式

def squeeze(char,s): 
    while char*2 in s: 
     s=s.replace(char*2,char) 
    return s 
print squeeze("*" , "AB***abc**def**AA***k") 
14

天真的方式做这种事情有re

re.sub('\*+', '*', text) 

用1个星号替换1个或多个星号的运行。对于正好有一个星号的运行,这个运行非常困难,只能保持静止。更好的是一个星号,以取代两种或两种以上星号运行:

re.sub('\*\*+', '*', text) 

这是非常值得做的:

\python27\python -mtimeit -s"t='a*'*100;import re" "re.sub('\*+', '*', t)" 
10000 loops, best of 3: 73.2 usec per loop 

\python27\python -mtimeit -s"t='a*'*100;import re" "re.sub('\*\*+', '*', t)" 
100000 loops, best of 3: 8.9 usec per loop 

注意,重新。sub会返回一个引用到输入字符串,如果它没有找到匹配,节省更多的磨损和撕裂你的电脑,而不是一个全新的字符串。

+0

+1这是一个很好的提示。虽然对于一个普通的Joe来说,每秒可能不会这样做几千次,但这个差别并不重要。前者取决于可读性。所以我建议,不要盲目地使用后者。 – Medorator 2014-09-12 19:34:35

+1

@Medorator不清楚可读性......一旦JAvg明白'\ X',跳转到'\ X \ X'对我来说似乎很小。也许'\ X {2,}'会更好?我希望JAvg不会盲目做任何事情。如果输出要求更改为“查找所有重复的星号”,则您会认为正则表达式已从1+更改为2+。 – 2017-02-04 01:30:19

1

您写道:

pattern.replace("*"\*, "*") 

您的意思是:

pattern.replace("\**", "*") 
#    ^^^^ 

你的真正用意:

pattern_after_substitution= re.sub(r"\*+", "*", pattern) 

它做你想要的。

0

为了这个例子,让我们假设你的角色是一个空间。

你也可以这样来做:

while True: 
    if " " in pattern: # if two spaces are in the variable pattern 
     pattern = pattern.replace(" ", " ") # replace two spaces with one 
    else: # otherwise 
     break # break from the infinite while loop 

此:

File Type      : Win32 EXE 
File Type Extension    : exe 
MIME Type      : application/octet-stream 
Machine Type     : Intel 386 or later, and compatibles 
Time Stamp      : 2017:04:24 09:55:04-04:00 

变为:

File Type : Win32 EXE 
File Type Extension : exe 
MIME Type : application/octet-stream 
Machine Type : Intel 386 or later, and compatibles 
Time Stamp : 2017:04:24 09:55:04-04:00 

,我觉得这比渣土周围变得更轻松re模块,它有时会让我有些恼火(我认为)。

希望有帮助。

0

这将适用于任意数量的连续星号,尽管您可能需要用其他字符串替换其他字符串,这些字符串在整个字符串中都是唯一的。

string = "begin*************end" 

    string.replace("**", "~*").replace("*~", "").replace("~*", "*").replace("**", "*") 

我相信正则表达式的方法通常比这个计算量更大。