2012-09-17 22 views
10

Tekrarlayan bir karakter desenine sahip bir dizim var, ör.Bir dizgede yinelenen karakter desenini kaldırmak için düzenli ifade

'xyzzyxxyzzyxxyzzyx' 

Ben en küçük tekrarlanan desenli böyle dize yerini alacak bir regex yazmaya gerek:

'xyzzyxxyzzyxxyzzyx' becomes 'xyzzyx', 

'abcbaccbaabcbaccbaabcbaccba' becomes 'abcbaccba' 
+0

Model bilinen mi, yoksa bir dizide tekrarlanan bir model mi arıyorsunuz? – Joel

+1

Sanırım en küçük yinelenen modeli arıyor. – arshajii

cevap

5

Kullanım aşağıdadır:

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

Temelde tekerrür bir kalıpla eşleşen (.+?)\1+, ve \1 ilk grubunda yakalanan yinelenen desen, ancak her şeyi kaldırır. Ayrıca burada bir isteksiz niteleyicinin kullanılmasının, yani +?'un regex geri izlemesini oldukça fazla yapacağı da not edilmelidir.

DEMO. En küçük tekrarlanan deseni istediğim için

+0

Buradaki sorun, bu durum için başarısız olmasıdır: >>> re.alt (r '(\ w +) \ 1+', r '\ 1', 'iiiiiiiiiiiiiiiiii') 'iiiiiiiii' yerine 'i' yerine – mercador

+0

@mercador: Görüyorum, yerine + + nicel isteksizini yapın açgözlü. Cevabımı güncelledim. –

4

, aşağıdaki gibi bir şey sizin için çalışması gerekir:

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

^ ve $ çapalar ederek dize ortasında eşleşmeleri alamadım emin olun ve sadece .+ yerine .+? kullanarak en kısa kalıbı elde edeceksiniz (sonuçları 'aaaaaaaaaa' gibi bir dize kullanarak karşılaştırın).

+1

Ve şunu unutmayın; eğer input_string '' a '* 1000000 +' b ''gibi bir şey varsa, bunun başarısız olması uzun zaman alabilir. – hobbs

+1

Geri döndürme olmaksızın herhangi bir regex fikri var mı? '. +?' Ağır geri dönüşe neden olur. – Kash

+0

'Perl Programlama' gibi bir kitap okursanız, 'ağır' örneklerle regeekslerin gerçeklenmesini bulabilirsiniz. Bence, düzenli ifadeler için hızlı bir görev değildir. – gaussblurinc

2

ilk grubu Bu normal ifadenin desen deneyin ve yakalamak: yenisatırlar

  • + nicelik dışında herhangi bir karakter en az 1 oluşumunu göstermek için dize başlangıcı için

    ^(.+?)\1+$ 
    
    • ^ çapa/satır
    • .
    • ?, açgözlülük yerine + tembel yapar, dolayısıyla Bu desen belirtmek için size nicelik ile
    • () yakalama grubu
    • \1+ geribaşvuru kısa deseni veren gerektiği dize/hat burada

    Testi onu sonu için bir kez

  • $ çapa en az tekrar: Rubular


    Yukarıdaki çözüm pek çok ktracking performansı etkiliyor. Bu dizelerde hangi karakterlere izin verilmediğini biliyorsanız, geri izlemeyi ortadan kaldıran olumsuz bir zincir kümesi kullanabilirsiniz. Örneğin, eğer beyaz boşluklara izin verilmiyorsa,