2009-11-03 7 views
13

पाइथन अपवादों को बढ़ाने से प्यार करता है, जो आमतौर पर महान होता है। लेकिन मुझे कुछ तारों का सामना करना पड़ रहा है जो मैं सी के एटोई/एटॉफ सेमेन्टिक्स का उपयोग करके पूर्णांक में परिवर्तित करना चाहता हूं - उदा। "3 में से 12", "3/12", "3/12" के atoi, सभी 3 बनना चाहिए; atof ("3.14 सेकंड") 3.14 बनना चाहिए; atoi ("-99 स्कोर") -99 होना चाहिए। निश्चित रूप से पाइथन में एटोई और एटॉफ फ़ंक्शंस हैं, जो एटॉय और एटॉफ़ और बिल्कुल पाइथन के स्वयं के इंट और फ्लोट कन्स्ट्रक्टर की तरह व्यवहार नहीं करते हैं।पाइथन atoi/atof

सबसे अच्छा मैं अब तक है, जो वास्तव में बदसूरत और कठिन है उपलब्ध विभिन्न नाव स्वरूपों के लिए विस्तार करने के लिए:

value = 1 
s = str(s).strip() 
if s.startswith("-"): 
    value = -1 
    s = s[1:] 
elif s.startswith("+"): 
    s = s[1:] 
try: 
    mul = int("".join(itertools.takewhile(str.isdigit, s))) 
except (TypeError, ValueError, AttributeError): 
    mul = 0 
return mul * value 

उत्तर

3

यह नियमित अभिव्यक्ति के साथ ऐसा करना बहुत सीधा है:

>>> import re 
>>> p = re.compile(r'[^\d-]*(-?[\d]+(\.[\d]*)?([eE][+-]?[\d]+)?)') 
>>> def test(seq): 
     for s in seq: 
      m = p.match(s) 
      if m: 
       result = m.groups()[0] 
       if "." in result or "e" in result or "E" in result: 
        print "{0} -> {1}".format(s, float(result)) 
       else: 
        print '"{0}" -> {1}'.format(s, int(result)) 
      else: 
       print s, "no match" 

>>> test(s) 
"1 0" -> 1 
"3 of 12" -> 3 
"3 1/2" -> 3 
"3/12" -> 3 
3.15 seconds -> 3.15 
3.0E+102 -> 3e+102 
"what about 2?" -> 2 
"what about -2?" -> -2 
2.10a -> 2.1 
+1

' atoi ("लगभग 2") के लिए ठीक से काम नहीं करता है, ''0' वापस लौटना चाहिए, क्योंकि यह' w 'से शुरू होता है 'और' w' एक अंक नहीं है। – Quuxplusone

6

शायद स्ट्रिंग है कि हो सकता है का केवल पहला भाग हड़पने के लिए एक त्वरित regex का उपयोग संख्यात्मक माना जाता है? कुछ की तरह ...

-?[0-9]+(?:\.[0-9]+)? 

तैरता के लिए और सिर्फ ints के लिए,

-?[0-9]+ 
+3

तैरता क्या मेरा अनुमान है कि सरलतम एल्गोरिथ्म मैं यहाँ देखने के लिए जा रहा हूँ है के लिए –

7

मुझे लगता है कि पुनरावृत्ति संस्करण पुनरावर्ती संस्करण

# Iterative 
def atof(s): 
    s,_,_=s.partition(' ') # eg. this helps by trimming off at the first space 
    while s: 
     try: 
      return float(s) 
     except: 
      s=s[:-1] 
    return 0.0 

# Recursive 
def atof(s): 
    try: 
     return float(s) 
    except: 
     if not s: 
      return 0.0 
     return atof(s[:-1]) 


print atof("3 of 12") 
print atof("3/12") 
print atof("3/12") 
print atof("3.14 seconds") 
print atof("314e-2 seconds") 
print atof("-99 score") 
print atof("hello world") 
+0

+1 भी उन में 'e' या' E' हो सकता है! –

+2

सरल, शायद, लेकिन वास्तव में कुशल नहीं है (विशेष रूप से यदि स्ट्रिंग का पाठ भाग संख्यात्मक भाग की तुलना में लंबा है)। – Amber

+0

यदि स्ट्रिंग में बहुत जंक हो सकता है तो आपको रिकर्सन के बजाय लूप का उपयोग करना होगा। यदि आप बहुत सारे रूपांतरण कर रहे हैं तो इसे करने के तेज तरीके हैं। –

36

से बेहतर है आप उत्सुक हैं, तो सी atoi की बिल्कुल कार्यक्षमता प्राप्त करने पर, इसका उपयोग क्यों न करें? उदाहरण के लिए, मेरे मैक,

>>> import ctypes, ctypes.util 
>>> whereislib = ctypes.util.find_library('c') 
>>> whereislib 
'/usr/lib/libc.dylib' 
>>> clib = ctypes.cdll.LoadLibrary(whereislib) 
>>> clib.atoi('-99foobar') 
-99 

लिनक्स, विंडोज, आदि, समान कोड सिवाय इसके कि आप एक अलग रास्ता अगर आप की जांच whereislib (केवल वास्तव में, वास्तव में अजीब प्रतिष्ठानों इस कोड को कभी असफल चाहिए देखेंगे काम करना चाहिए में पर सी रनटाइम लाइब्रेरी खोजने के लिए)।

यदि आप प्रत्यक्ष सी लाइब्रेरी उपयोग से परहेज करने के इच्छुक हैं, तो मुझे लगता है कि आप प्रासंगिक उपसर्ग को पकड़ सकते हैं, उदा। एक आरई जैसे r'\s*([+-]?\d+)', और उस पर int आज़माएं।

+2

+1 ग्रेट उत्तर! –

+0

मेरा अनुमान प्लेटफार्म निर्भरता है (इस बात का जिक्र नहीं है कि पुस्तकालय सैद्धांतिक रूप से एक ही मंच पर भी विभिन्न स्थानों में रह सकते हैं) के खिलाफ सबसे बड़ा तर्क होगा। – Amber

+1

@ एंड्रयू, टीएक्स! @Dav, हां, आपको libc के DLL का पता लगाना होगा (इसमें अलग-अलग नाम और पथ हो सकते हैं), लेकिन 'ctypes.util.find_library' मदद करता है - मैंने इसका उपयोग करने के तरीके को दिखाने के लिए अभी जवाब संपादित किया है। –

0

मुझे लगता है कि मैं इसे चार से चार करते देगा:

def myatof(s): 
    try: 
     return float(s); 
    except: 
     last_result = None 
     for i in range(1, len(s)): 
      try: 
       last_result = float(s[:i]) 
      except: 
       return last_result 
    return last_result 
+1

यह '314e-2' –

-1

यह कैसे के बारे में?

num=int(q.join(re.findall(r'[\d-]',s))) 
+0

यहां q = '' शुरुआत में। एस इनपुट स्ट्रिंग संख्या अंतिम उत्तर है। – abhilash