2013-02-27 28 views
5

मैं इस तरह के तार में [0-9] और [A-Z] अलग करने के लिए कोशिश कर रहा हूँ की तरह तार में संख्या और अक्षर अलग करने के लिए:नियमित अभिव्यक्ति का उपयोग कैसे करें "30M1000N20M"

100M 
20M1D80M 
20M1I79M 
20M10000N80M 

मैं अजगर re मॉड्यूल उपयोग करने की कोशिश, और

>>>import re 
>>>num_alpha = re.compile('(([0-9]+)([A-Z]))+') 
>>>str1="100M" 
>>>n_a_match = num_alpha.match(str1) 
>>>n_a_match.group(2), n_a_match.group(3) 

100,M #just what I want 

>>>str1="20M10000N80M" 
>>>n_a_match = num_alpha.match(str1) 
>>>n_a_match.groups() 

('80M', '80', 'M') #only the last one, how can I get the first two? 
#expected result ('20M','20','M','10000N','10000','N','80M','80','M') 

यह नियमित अभिव्यक्ति श्रृंखलाएं जिनमें केवल एक मैच होते हैं, लेकिन मैचों में से नहीं कई समूहों के लिए अच्छी तरह से काम करता है: निम्नलिखित कोड मैं प्रयोग किया जाता है। नियमित अभिव्यक्तियों का उपयोग करके मैं इसे कैसे संभाल सकता हूं?

उत्तर

3

मैं re.findall उपयोग करने का सुझाव। यदि आप सूची बनाने के बजाय परिणामों पर पुन: प्रयास करना चाहते हैं, तो आप इसके बजाय re.finditer का उपयोग कर सकते हैं।

>>> re.findall("(([0-9]+)([A-Z]))", "20M10000N80M") 
[('20M', '20', 'M'), ('10000N', '10000', 'N'), ('80M', '80', 'M')] 

आप संयुक्त संख्या + पत्र स्ट्रिंग नहीं करना चाहते हैं, तो आप मैच से बाहरी कोष्ठकों को हटा सकते हैं और सिर्फ अलग अलग हिस्सों मिलती है::

>>> re.findall("([0-9]+)([A-Z])", "20M10000N80M") 
[('20', 'M'), ('10000', 'N'), ('80', 'M')] 
यहाँ है कि कैसे काम करेगा का एक उदाहरण है

या, यदि आप बिल्कुल टुपल्स नहीं चाहते हैं (और आपको विकृत इनपुट के बारे में चिंता करने की आवश्यकता नहीं है, जैसे पंक्ति में कई अक्षरों के साथ तार), तो आप पैटर्न को एक विकल्प में बदल सकते हैं, और मूल्य प्राप्त कर सकते हैं एक करके एक:

>>> re.findall("([0-9]+|[A-Z])", "20M10000N80M") 
['20', 'M', '10000', 'N', '80', 'M'] 
+0

ग्रेट। मुझे 'findall() 'निष्पादन याद नहीं आया। अंतिम नियमित अभिव्यक्ति की सराहना करें। – ct586

+0

सभी उत्तरों महान हैं। अगर अनुमति है, तो मैं तीनों का चयन करूंगा। मैंने इसे दूसरी नियमित अभिव्यक्ति के लिए चुना है जो मैं चाहता हूं। फिर, सभी को धन्यवाद। – ct586

3

split विधि का उपयोग कर प्रयास करें:

>>> str1="20M10000N80M" 
>>> num_alpha = re.compile('(([0-9]+)([A-Z]))') 
>>> l = num_alpha.split(str1) 
>>> l 
['', '20M', '20', 'M', '', '10000N', '10000', 'N', '', '80M', '80', 'M', ''] 

ध्यान दें कि मैं regex में + हटा दिया।

और रिक्त स्ट्रिंग दूर करने के लिए, एक सूची जनरेटर:

>>> l_without_empty = [x for x in l if x != ''] 
['20M', '20', 'M', '10000N', '10000', 'N', '80M', '80', 'M'] 

संपादित करें:

या, टिप्पणी में कहा है:

>>> l_without_empty = [x for x in l if x] 
['20M', '20', 'M', '10000N', '10000', 'N', '80M', '80', 'M'] 
+2

छोटी टिप्पणी, आप 'x! = ''' 'के बजाय 'अगर नहीं x' का उपयोग कर सकते हैं। कोई मुद्दा नहीं, लेकिन केवल FYI – Serdalis

+0

ओह, अच्छा! धन्यवाद। – braunmagrin

+3

रुको, यह सही नहीं है। 'यदि x नहीं है तो' x 'होना चाहिए; आप उन लोगों को रखना चाहते हैं जिनके पास 'बूल (x) == True' है। 'यदि नहीं x' केवल उन लोगों को ही रखेगा जो * खाली हैं। – DSM

2

एक अन्य विकल्प के बजाय re.findall के लिए जाने के लिए है: एक टपल के रूप में

>>> string = "20M10000N80M" 
>>> groups = re.findall(r'((\d+)(\D+))', string) 
[('20M', '20', 'M'), ('10000N', '10000', 'N'), ('80M', '80', 'M')] 

तो, आप देख सकते हैं विभिन्न समूहों, tuples के रूप में लौटा तो, अगर आप वास्तव में यह चाहते के रूप में आप को पेश - आप इसे समतल कर सकते हैं:

>>> from itertools import chain 
>>> tuple(chain.from_iterable(groups)) 
('20M', '20', 'M', '10000N', '10000', 'N', '80M', '80', 'M') 
+0

धन्यवाद, बहुत अच्छा। मॉड्यूल 'itertools' सीखना मेरी खुशी है। – ct586

+0

@ सीटी 586 यह एक बहुत ही उपयोगी और शक्तिशाली पुस्तकालय है - आपके सीखने में मजा लें! –

संबंधित मुद्दे