我具有与每个字符的字符串通过管道字符(包括"|"
š本身)被分离的字符的单个实例,例如:替换有时加倍
"f|u|n|n|y||b|o|y||a||c|a|t"
我想更换所有"|"
S的不相邻的另一个"|"
什么也没有,得到结果:
"funny|boy|a|cat"
我试着用mytext.replace("|", "")
,但除去一切,使得一个长字。
我具有与每个字符的字符串通过管道字符(包括"|"
š本身)被分离的字符的单个实例,例如:替换有时加倍
"f|u|n|n|y||b|o|y||a||c|a|t"
我想更换所有"|"
S的不相邻的另一个"|"
什么也没有,得到结果:
"funny|boy|a|cat"
我试着用mytext.replace("|", "")
,但除去一切,使得一个长字。
您可以先用别的东西替换双管,以确保在删除单管后仍可识别它们。然后你替换这些回管:
>>> t = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> t.replace('||', '|-|').replace('|', '').replace('-', '|')
'funny|boy|a|cat'
你应该尽量选择一个替代值是一个安全的临时值,并且不自然地出现在你的文字。否则,即使原本不是双管,也会遇到冲突,即该字符被替换。因此,如果您的文本可能包含破折号,请不要像上面那样使用破折号。您也可以一次使用多个字符,例如:'<THIS IS A TEMPORARY PIPE>'
。
如果你想完全避免这种冲突,你也可以解决这个完全不同的问题。例如,你可以用双管第一分割字符串并在每个子进行置换,最终将它们连接到一起:
>>> '|'.join([s.replace('|', '') for s in t.split('||')])
'funny|boy|a|cat'
当然,你也可以使用正则表达式来替换那些管道后面没有其他管道:
>>> import re
>>> re.sub('\|(?!\|)', '', t)
'funny|boy|a|cat'
使用Sentinel值
由~
更换||
。这将记住||
。然后删除|
s。最后用|
重新替换它们。
>>> s = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> s.replace('||','~').replace('|','').replace('~','|')
'funny|boy|a|cat'
另一个更好的办法是使用的事实,他们几乎替代文本。解决的办法是让他们完全替代的......
s.replace('||','|||')[::2]
这比正则表达式解决方案快5倍,编译后的正则表达式'700 ns vs 3.9μs' –
@Padraic Yep,它们是“Regex”;) –
如果有人在输入中使用sentinel值,这个解决方案是否仍然有效? – hagello
您可以使用正则表达式positive look ahead更换的后边带有字母字符的点子:
>>> import re
>>> st = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> re.sub(r'\|(?=[a-z]|$)',r'',st)
'funny|boy|a|cat'
这对于'st =“f | | | n | n | y || b | o | y || a || c | a | t |“',你需要抓住结尾管道 –
@PadraicCunningham是的,我添加了锚点'$'。谢谢你的提示。 – Kasramvd
这可以用一个相对可以实现简单的regex,而不必链str.replace
:
>>> import re
>>> s = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> re.sub('\|(?!\|)' , '', s)
'funny|boy|a|cat'
说明:\ |将寻找一个|
characte |(\?!) r之后不是另一个|
字符。 (?!foo)意味着消极的前瞻,确保你所匹配的任何东西都不会跟着foo。
+1当格式更改为允许使用'-'字符时,此方法不会中断,这与当前顶级答案不同。 –
@ BlueRaja-DannyPflughoeft True!另外看看Padraic的[时间比较](http://stackoverflow.com/a/34472163/4099593)。 Regards –
@BhargavRao除非您正在处理数百万个字符串或数百万字符的字符串,否则性能无关紧要。 –
使用正则表达式。
import re
line = "f|u|n|n|y||b|o|y||a||c|a|t"
line = re.sub("(?!\|\|)(\|)", "", line)
print(line)
输出:
funny|boy|a|cat
你不需要一个捕获组。 –
一个与捕获组另一个正则表达式选项。
>>> import re
>>> re.sub(r'\|(\|?)', r'\1', "f|u|n|n|y||b|o|y||a||c|a|t")
'funny|boy|a|cat'
说明:
\|
- 匹配所有管道字符。 (\|?)
- 捕获以下管道字符(如果存在)。然后用\1
替换比赛将为您带来第一个捕获组的内容。所以在单个点的位置,它会给出一个空字符串,并在||
,它会带来第二个管道字符。
通过字和非字边界另一个技巧...
>>> re.sub(r'\b\|\b|\b\|\B', '', "f|u|n|n|y||b|o|y||a||c|a|t|")
'funny|boy|a|cat'
另一个使用一个负回顾后..
>>> re.sub(r'(?<!\|)\|', '', "f|u|n|n|y||b|o|y||a||c|a|t|")
'funny|boy|a|cat'
奖金......
>>> re.sub(r'\|(\|)|\|', lambda m: m.group(1) if m.group(1) else '', "f|u|n|n|y||b|o|y||a||c|a|t")
'funny|boy|a|cat'
哦,'re.sub'可以用一个可调用的...时间来重写一些代码。 +1 – timgeb
你不知道吗?然后你今天学到了新的东西:-) –
如果你将使用正则表达式,这是最快的方法是分裂和加入:
In [18]: r = re.compile("\|(?!\|)")
In [19]: timeit "".join(r.split(s))
100000 loops, best of 3: 2.65 µs per loop
In [20]: "".join(r.split(s))
Out[20]: 'funny|boy|a|cat'
In [30]: r1 = re.compile('\|(?!\|)')
In [31]: timeit r1.sub("", s)
100000 loops, best of 3: 3.20 µs per loop
In [33]: r2 = re.compile("(?!\|\|)(\|)")
In [34]: timeit r2.sub("",s)
100000 loops, best of 3: 3.96 µs per loop
的str.split
和str.replace
方法仍然较快:
In [38]: timeit '|'.join([ch.replace('|', '') for ch in s.split('||')])
The slowest run took 11.18 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 1.71 µs per loop
In [39]: timeit s.replace('||','|||')[::2]
1000000 loops, best of 3: 536 ns per loop
In [40]: timeit s.replace('||','~').replace('|','').replace('~','|')
1000000 loops, best of 3: 881 ns per loop
根据什么可以是字符串将决定str.replace
办法,但str.split
方法将工作无论是在字符串中哪些字符。
没错,我们现在有结果证明也:) –
“*”字符(包括“|”)被“|”字符*“分隔”并不是真的。如果那是真的,你就会有''f | u | n | n | y ||| b | o | y ||| a ||| c | a | t“'。 – zvone