2012-09-17 6 views
10

में दोहराए गए वर्ण पैटर्न को हटाने के लिए Regex मेरे पास एक स्ट्रिंग है जिसमें दोहराया गया वर्ण पैटर्न हो सकता है, उदा।एक स्ट्रिंग

'xyzzyxxyzzyxxyzzyx' 

मैं एक regex कि अपनी छोटी से छोटी दोहराया पैटर्न के साथ इस तरह के स्ट्रिंग की जगह लेंगे लिखने की ज़रूरत:

'xyzzyxxyzzyxxyzzyx' becomes 'xyzzyx', 

'abcbaccbaabcbaccbaabcbaccba' becomes 'abcbaccba' 
+0

क्या पैटर्न ज्ञात है, या आप स्ट्रिंग में किसी भी दोहराने वाले पैटर्न की तलाश में हैं? – Joel

+1

वह मुझे लगता है कि सबसे छोटा दोहराव पैटर्न की तलाश में है। – arshajii

उत्तर

5

उपयोग निम्नलिखित:

> re.sub(r'(.+?)\1+', r'\1', 'xyzzyxxyzzyxxyzzyx') 
'xyzzyx' 
> re.sub(r'(.+?)\1+', r'\1', 'abcbaccbaabcbaccbaabcbaccba') 
'abcbaccba' 
> re.sub(r'(.+?)\1+', r'\1', 'iiiiiiiiiiiiiiiiii') 
'i' 

यह मूल रूप से एक पैटर्न है कि स्वयं को दोहराता है से मेल खाता है (.+?)\1+, और सब कुछ हटा देता है लेकिन दोहराव पैटर्न, जो पहले समूह \1 में कब्जा कर लिया गया है। यह भी ध्यान रखें कि यहां एक अनिच्छुक क्वालीफायर का उपयोग करके, यानी +? रेगेक्स बैकट्रैक को काफी कुछ कर देगा।

DEMO

+0

इसके साथ समस्या यह है कि यह इस मामले के लिए विफल रहता है: >>> पुन:।उप (आर '(\ डब्ल्यू +) \ 1+', आर '\ 1', 'iiiiiiiiiiiiiiiiii') 'iiiiiiiii' 'i' – mercador

+0

@mercador के बजाय उपज करता है: मैं देखता हूं, '+ 'क्वांटिफ़ायर अनिच्छुक करने के बजाय लालची। मैंने अपना जवाब अपडेट कर लिया है। –

4

जब से तुम सबसे छोटी दोहरा पैटर्न चाहते हैं, निम्नलिखित की तरह कुछ आप के लिए काम करना चाहिए:

re.sub(r'^(.+?)\1+$', r'\1', input_string) 

^ और $ एंकर सुनिश्चित करें कि आप स्ट्रिंग के बीच में से मेल खाता है नहीं मिलता है, और द्वारा .+ के बजाय .+? का उपयोग करके आपको सबसे छोटा पैटर्न मिलेगा ('aaaaaaaaaa' जैसे स्ट्रिंग का उपयोग करके परिणामों की तुलना करें)।

+1

और ध्यान रखें कि 'input_string' कुछ "* 1000000 +" b "' की तरह कुछ विफल होने में विफल होने में काफी समय लग सकता है। – hobbs

+1

बैकट्रैकिंग के बिना रेगेक्स के किसी भी विचार? '। +? 'भारी बैकट्रैकिंग का कारण बन जाएगा। – Kash

+0

यदि आप 'प्रोग्रामिंग पर्ल' जैसी पुस्तक पढ़ते हैं, तो आप 'भारी' उदाहरणों के साथ रेगेक्स का अहसास पा सकते हैं। मुझे लगता है, यह regexs के लिए एक त्वरित काम नहीं है। – gaussblurinc

2

इस regex पैटर्न की कोशिश करो और पहले समूह पर कब्जा: स्ट्रिंग की शुरुआत के लिए

^(.+?)\1+$ 
  • ^ लंगर/लाइन
  • . नई-पंक्तियों
  • + परिमाणक को छोड़कर किसी भी चरित्र कम से कम 1 घटना निरूपित करने के लिए
  • ? लालची के बजाय + आलसी बनाता है, इसलिए आप उस पैटर्न को निरूपित करने के कम से कम पैटर्न देने
  • () कैप्चरिंग समूह
  • \1+ परिमाणक साथ backreference चाहिए दोहराने कम से कम एक बार
  • $ स्ट्रिंग/लाइन

टेस्ट इसे यहाँ के अंत के लिए लंगर: Rubular


उपर्युक्त समाधान बहुत सारे बीएसी करता है प्रदर्शन को प्रभावित करने के लिए ktracking। यदि आप जानते हैं कि इन तारों में कौन से पात्रों की अनुमति नहीं है, तो आप एक नकारात्मक गुणित सेट का उपयोग कर सकते हैं जो बैकट्रैकिंग को समाप्त करता है। उदाहरण के लिए, यदि व्हाइटस्पेस की अनुमति नहीं है, तो

^([^\s]+)\1+$