पायथन रेगेक्स सभी ओवरलैपिंग मैचों का पता लगाता है?


98

मैं पायथन 2.6 में पुनः उपयोग करके संख्याओं की एक बड़ी श्रृंखला के भीतर हर 10 अंकों की श्रृंखला खोजने की कोशिश कर रहा हूं।

मैं आसानी से कोई ओवरलैपिंग मैच हासिल नहीं कर पा रहा हूं, लेकिन मैं नंबर सीरीज में हर मैच चाहता हूं। उदाहरण के लिए।

"123456789123456789" में

मुझे निम्नलिखित सूची प्राप्त करनी चाहिए:

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

मुझे "लुकहैड" के संदर्भ मिले हैं, लेकिन मैंने जो उदाहरण देखे हैं वे केवल बड़े समूहों के बजाय संख्याओं के जोड़े दिखाते हैं और मैं उन्हें दो अंकों से आगे नहीं बदल सका हूं।


6
प्रस्तुत समाधान तब काम नहीं करेंगे जब ओवरलैपिंग मैच एक ही बिंदु पर शुरू होते हैं, उदाहरण के लिए, "एबीसी" के खिलाफ "ए | एबी | एबीसी" का मिलान केवल एक परिणाम देगा। क्या इसके लिए कोई समाधान है जिसमें कई बार कॉलिंग मैच () शामिल नहीं है, मैन्युअल रूप से 'एंड' सीमा का ट्रैक रखता है?
वीटोर डे आराउजो

@ VítorDeAraújo: ओवरलेपिंग रेगीक्स (a|ab|abc)को आमतौर पर नेस्टेड कैप्चर-ग्रुप्स के साथ नॉन-ओवरलैपिंग वाले के रूप में फिर से लिखा जा सकता है, उदाहरण के लिए (a(b(c)?)?)?, जहां हम एक मैच को अनसुना करते हुए सबसे बाहरी (यानी सबसे बाएं) कैप्चर ग्रुप को अनदेखा करते हैं; माना जाता है कि यह थोड़ा दर्दनाक और कम सुपाच्य है। यह मैच करने के लिए अधिक प्रदर्शन करने वाला रेगेक्स भी होगा।
2

जवाबों:


175

लुकहैड के अंदर कैप्चरिंग ग्रुप का उपयोग करें। लुकहेड उस पाठ को कैप्चर करता है जिसमें आप रुचि रखते हैं, लेकिन वास्तविक मैच तकनीकी रूप से शून्य-चौड़ाई के विकल्प से पहले दिखता है, इसलिए मैच तकनीकी रूप से गैर-अतिव्यापी हैं:

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
मेरा उत्तर इस से कम से कम 2 गुना तेज है। लेकिन यह समाधान मुश्किल है, मैं इसे बढ़ाता हूं।
चश्मदीद

16
स्पष्टीकरण = पैटर्न (10 अंक) की खोज करने के बजाय, यह पैटर्न के अनुसार कुछ भी खोजता है। तो यह स्ट्रिंग की स्थिति 0, स्ट्रिंग की स्थिति 1 और इसी तरह की स्थिति ढूंढता है। फिर यह समूह (1) को पकड़ता है - मिलान पैटर्न और उन लोगों की सूची बनाता है। बहुत ही शांत।
ताल वेइस

मुझे नहीं पता था कि आप लुकहेड्स के अंदर मेल खाने वाले समूहों का उपयोग कर सकते हैं, जिन्हें आम तौर पर एक मैच में शामिल नहीं किया जाना चाहिए (और मिलान किए गए उपसमूह वास्तव में पूर्ण मैच नहीं दिखाई देते हैं)। जैसा कि यह तकनीक अभी भी पायथन 3.4 में काम करती है, मुझे लगता है कि इसे बग के बजाय एक विशेषता माना जाता है।
JAB

10
मैं StackOverflow में शामिल हुआ, प्रश्नों का उत्तर दिया, और अपनी प्रतिष्ठा प्राप्त की ताकि मैं इस उत्तर को बना सकूं। मैं अब तक पाइथन 2.4 के साथ फंस गया हूं, इसलिए मैं पाइथन 3 के अधिक उन्नत रेगेक्स फ़ंक्शंस का उपयोग नहीं कर सकता हूं, और यह केवल विचित्र चालबाजी का प्रकार है जिसे मैं देख रहा था।
TheSoundDefense

2
क्या आप कोड में अधिक स्पष्टीकरण जोड़ सकते हैं। स्टैक ओवरफ्लो के अनुसार इसका सबसे अच्छा तरीका नहीं है, बस एक उत्तर में कोड है। यह निश्चित रूप से लोगों की मदद करेगा।
अक्षय हजारी

77

आप तृतीय-पक्ष regexमॉड्यूल (नहीं re) का उपयोग करने का भी प्रयास कर सकते हैं , जो ओवरलैपिंग मैचों का समर्थन करता है।

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

17

मैं रीगेक्स का शौकीन हूं, लेकिन यहां उनकी जरूरत नहीं है।

केवल

s =  "123456789123456789"

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

परिणाम

1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

10
Regexes की यहां केवल इसलिए आवश्यकता नहीं है क्योंकि आप "संख्याओं की एक बड़ी श्रृंखला के भीतर" विशेष ज्ञान को लागू कर रहे हैं, इसलिए आप पहले से ही जानते हैं कि प्रत्येक स्थिति 0 <= i < len(s)-n+110-अंकों के मैच की शुरुआत की गारंटी है। इसके अलावा, मुझे लगता है कि आपके कोड को गति दी जा सकती है, गति के लिए कोड-गोल्फ के लिए दिलचस्प होगा।
smci
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.