Python normal ifadesi tüm örtüşen eşleşmeleri buluyor mu?


101

Python 2.6'da re kullanarak daha büyük bir sayı dizisi içindeki her 10 basamaklı sayı dizisini bulmaya çalışıyorum.

Çakışan eşleşmeleri kolayca yakalayabiliyorum, ancak sayı serisindeki her maçı istiyorum. Örneğin.

"123456789123456789" içinde

Aşağıdaki listeyi almalıyım:

[1234567891,2345678912,3456789123,4567891234,5678912345,6789123456,7891234567,8912345678,9123456789]

Bir "önden okuma" için referanslar buldum, ancak gördüğüm örnekler daha büyük gruplamalar yerine yalnızca sayı çiftlerini gösteriyor ve bunları iki rakamın ötesine çeviremedim.


6
Sunulan çözümler, örtüşen eşleşmeler aynı noktada başladığında çalışmayacaktır, örneğin "a | ab | abc" ile "abcd" nin eşleştirilmesi yalnızca bir sonuç döndürür. Match () 'i birden çok kez çağırmayı,' bitiş 'sınırını manuel olarak takip etmeyi içermeyen bir çözüm var mı?
Vítor De Araújo

@ VítorDeAraújo: gibi çakışan normal ifadeler (a|ab|abc)genellikle iç içe geçmiş yakalama gruplarıyla örtüşmeyenler olarak yeniden yazılabilir, örneğin (a(b(c)?)?)?, bir eşleşmeyi açarken en dıştaki (yani en soldaki) yakalama grubu dışında her şeyi göz ardı ettiğimiz yerde; kuşkusuz bu biraz acı verici ve daha az okunaklı. Bu aynı zamanda eşleşmesi için daha performanslı bir normal ifade olacaktır.
smci

Yanıtlar:


179

Önden bakıldığında yakalama grubu kullanın. Önden bakış, ilgilendiğiniz metni yakalar, ancak gerçek eşleşme teknik olarak önden önceki sıfır genişlikli alt dizedir, bu nedenle eşleşmeler teknik olarak çakışmaz:

import re 
s = "123456789123456789"
matches = re.finditer(r'(?=(\d{10}))',s)
results = [int(match.group(1)) for match in matches]
# results: 
# [1234567891,
#  2345678912,
#  3456789123,
#  4567891234,
#  5678912345,
#  6789123456,
#  7891234567,
#  8912345678,
#  9123456789]

2
Cevabım bundan en az 2 kat daha hızlı. Ama bu çözüm aldatıcı, ona oy veriyorum.
eyquem

16
Açıklama = kalıbı aramak yerine (10 hane), kalıp tarafından TAKİP EDİLEN her şeyi arar. Böylece dizenin 0. konumunu, dizenin 1. konumunu vb. Bulur. Sonra grup (1) - eşleşen örüntüyü alır ve bunların bir listesini yapar. Çok havalı.
Tal Weiss

10
StackOverflow'a katıldım, soruları yanıtladım ve bu yanıta oy verebilmek için itibarımı yükselttim. Şimdilik Python 2.4 ile sıkışıp kaldım, bu yüzden Python 3'ün daha gelişmiş regex işlevlerini kullanamıyorum ve bu tam da aradığım türden tuhaf hile.
TheSoundDefense

2
Koda daha fazla açıklama ekleyebilir misiniz? Yığın Taşması'na göre en iyi yol değil, sadece bir cevapta koda sahip olmak. Kesinlikle insanlara yardım edecek.
Akshay Hazari

1
Bu gerçekten faydalıdır. Teşekkürler: D
Sreekiran

80

Üst üste gelen eşleşmeleri destekleyen üçüncü taraf regexmodülünü (değil re) kullanmayı da deneyebilirsiniz .

>>> import regex as re
>>> s = "123456789123456789"
>>> matches = re.findall(r'\d{10}', s, overlapped=True)
>>> for match in matches: print(match)  # print match
...
1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

Anlıyorum:TypeError: findall() got an unexpected keyword argument 'overlapped'
Carsten

@Carsten: Öncelikle regexmodülü kurmanız gerekiyor :pip install regex
David C

Bu işe yaradı, teşekkürler. Normal ifade yüklü değilse bir içe aktarma hatası alacağımı düşünürdüm
Carsten

17

Normal ifadeleri severim ama burada gerekli değiller.

Basitçe

s =  "123456789123456789"

n = 10
li = [ s[i:i+n] for i in xrange(len(s)-n+1) ]
print '\n'.join(li)

sonuç

1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

10
Burada normal ifadelere ihtiyaç yoktur, çünkü "daha büyük bir sayı dizisi içinde" özel bilgiyi uyguluyorsunuz, bu nedenle zaten her pozisyonun 0 <= i < len(s)-n+110 basamaklı bir eşleşmenin başlangıcı olacağının garantili olduğunu biliyorsunuz . Ayrıca kodunuzun hızlandırılabileceğini, hız için kod golfünün ilginç olacağını düşündüm.
smci
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.