2017-08-31 78 views
1

有沒有辦法按發生順序匹配唯一的字符組(在下面的情況下是字),純粹是在正則表達式中?如果是這樣,那麼表達式與非正則表達式解決方案的效率如何比較?我正在使用Python的風格,但我也會對其他任何風格的解決方案感興趣。在保持順序的情況下匹配唯一的組

這裏是一個樣本案例:

string = 'the floodwaters are rising along the coast' 
unique = ['the', 'floadwaters', 'are', 'rising', 'along', 'coast'] 

在Python的正則表達式的混合解決方案,我可以配合我想要的組,並用一個列表理解,以便移除重複,同時維持秩序。

groups = re.findall('[a-zA-Z]+', string) 
unique = [g for i, g in enumerate(groups) if g not in groups[:i]] 

該網站還有類似的問題,比如one that addresses matching unique words。但是,從接受的答案中得出的表達式與給定組最遠的發生次數相匹配,而我想要匹配發生的第一次事件。下面是一個表達:

(\w+\b)(?!.*\1\b) 
+0

正則表達式庫有所不同。在Python中,您可以使用PyPi'regex'庫,並使用['\ b(\ w +)\ b(?<!(?:。* \ b \ 1 \ b){2})'](http:/ /regexstorm.net/tester?p=%5cb%28%5cw%2b%29%5cb%28%3f%3c!%28%3f%3a.*%5cb%5c1%5cb%29%7b2%7d%29&i =在+洪水+爲+沿着上升+ + +的海岸)。而在.NET中,你也可以使用它。 –

+0

通常,以C++中的_unique_爲例,順序不會被保留。這是因爲該列表必須先排序。 – sln

+0

並且'(\ w + \ b)(?!。* \ 1 \ b)'與他們第一次出現時的單詞不匹配。它最終會匹配dups,而不是開始。你最好的選擇是分裂以獲得所有的單詞,然後做你自己的保護。正則表達式這將是難以置信slowww ........ – sln

回答

2

這類任務的唯一正則表達式的解決方案,纔可能有無限寬回顧後。

然而,這樣的正則表達式的解決方案應該考慮使用時輸入較短:在輸入字符串超過100個字將使它很慢,由於回溯那是必然的這個案例。因此,對於學習目的,我將分享僅支持.NET和Python PyPi regex庫的正則表達式(在Vim中也可以這樣做,因爲它的lookbehind也是無限寬度,但我猜這裏有用這個強大的工具更簡單的方法)。

(?s)\b(\w+)\b(?<!^.*\b\1\b.*\b\1\b) 

regex demo

(?s)部分是一個內聯改性劑,使.匹配所有換行符。您可以在Python regex中使用regex.DOTALL

詳細

  • \b - 初始字邊界
  • (\w+) - 第1組:一個或多個單詞字符
  • \b - 尾隨字邊界
  • (?<!^.*\b\1\b.*\b\1\b) - 無限寬度負回顧後那如果匹配到組1的單詞恰好在其自身之前出現一次,則匹配失敗如果,立即到當前位置的左側(即之後的字捕獲),還有的模式序列:
    • ^ - 字符串的開始
    • .*\b\1\b - 任何零個或多個字符,因爲許多儘可能,然後將相同的值在第1組作爲一個整體字
    • .*\b\1\b - 同上(需要以匹配所捕獲的字,由於反向預搜索被消耗字之後使用

.*在看起來後面會導致很多回溯,而且模式總體上工作起來相當慢,而且輸入很慢並且速度很慢,最終可能會導致超時。

相關問題