我具有與每個字符的字符串通過管道字符(包括"|"
š本身)被分離的字符的單個實例,例如:替換有時加倍
"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