2013-04-22 10 views
8

यहाँ की एक सूची में शब्द लंबाई के अनुपात में स्वर गिना जा रहा है मेरी समारोह के लिए कोड है ।शब्द

क्या ऐसा करने का कोई बेहतर तरीका है?

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

import time 

    class vowelProportions(object): 
     """ 
     A series of methods that all calculate the vowel/word length ratio 
     in a list of words. 
     """ 

     WORDLIST_FILENAME = "words_short.txt" 

     def __init__(self): 
      self.wordList = self.buildWordList() 
      print "Original: " + str(self.calcMeanTime(10000, self.cvpOriginal, self.wordList)) 
      print "Generator: " + str(self.calcMeanTime(10000, self.cvpGenerator, self.wordList)) 
      print "Count: " + str(self.calcMeanTime(10000, self.cvpCount, self.wordList)) 
      print "Translate: " + str(self.calcMeanTime(10000, self.cvpTranslate, self.wordList)) 

     def buildWordList(self): 
      inFile = open(self.WORDLIST_FILENAME, 'r', 0) 
      wordList = [] 
      for line in inFile: 
       wordList.append(line.strip().lower()) 
      return wordList 

     def cvpOriginal(self, wordList): 
      """ My original, slow algorithm""" 
      VOWELS = 'aeiou' 
      ratios = [] 

      for word in wordList: 
       numVowels = 0 
       for char in word: 
        if char in VOWELS: 
         numVowels += 1 
       ratios.append(numVowels/float(len(word))) 

      return ratios 

     def cvpGenerator(self, wordList): 
      """ Using a generator expression """ 
      return [sum(char in 'aeiou' for char in word)/float(len(word)) for word in wordList] 

     def cvpCount(self, wordList): 
      """ Using str.count() """ 
      return [sum(word.count(char) for char in 'aeiou')/float(len(word)) for word in wordList] 

     def cvpTranslate(self, wordList): 
      """ Using str.translate() """ 
      return [len(word.translate(None, 'bcdfghjklmnpqrstxyz'))/float(len(word)) for word in wordList] 

     def timeFunc(self, func, *args): 
      start = time.clock() 
      func(*args) 
      return time.clock() - start 

     def calcMeanTime(self, numTrials, func, *args): 
      times = [self.timeFunc(func, *args) for x in range(numTrials)] 
      return sum(times)/len(times) 

उत्पादन था (200 शब्दों की एक सूची के लिए):

Original: 0.0005613667 
Generator: 0.0008402738 
Count: 0.0012531976 
Translate: 0.0003343548 

हैरानी की बात है,

मैं एल्गोरिदम @ExP निम्नलिखित वर्ग के साथ प्रदान की जांच की जनरेटर और गणना मूल से भी धीमी थी (अगर मेरा कार्यान्वयन गलत था तो कृपया मुझे बताएं)।

मैं जॉन के समाधान का परीक्षण करना चाहता हूं, लेकिन पेड़ों के बारे में कुछ भी नहीं जानता।

+2

मुझे लगता है कि यह ध्यान देने योग्य होना चाहिए कि आपको शब्द (low) ('aeiouAEIOU''' या '(2) शब्द के लिए पहले शब्द (lower() के लिए पहले बदलना चाहिए:' – ryrich

+0

जब तक सूची में वे शब्द नहीं हैं जो लोअरकेस हैं – piokuc

+0

@ryrich जिस सूची में मैं काम कर रहा हूं वह केवल लोअरकेस शब्द है, लेकिन धन्यवाद - मैं इसका उल्लेख करना भूल गया। – paulwithap

उत्तर

4

आपको सबसे निचले पाश को अनुकूलित करना चाहिए।

मुझे पूरा यकीन है कि कई वैकल्पिक दृष्टिकोण हैं। यहां मैं अभी क्या कर सकता हूं। मुझे यकीन नहीं है कि वे गति में तुलना करेंगे (एक दूसरे के संबंध में और आपके समाधान के लिए)।

numVowels = sum(x in 'aeiou' for x in word) 
  • str.count() का उपयोग करना::

    • एक जनरेटर अभिव्यक्ति का उपयोग करते हुए

      numVowels = sum(word.count(x) for x in 'aeiou') 
      
    • str.translate() का उपयोग (यह मानते हुए कोई बड़े अक्षरों या विशेष प्रतीकों देखते हैं):

      numVowels = len(word.translate(None, 'bcdfghjklmnpqrstxyz')) 
      
    • 012,

    इनमें से सभी के साथ, आप पूरे कार्य को list.append() के बिना एक ही पंक्ति में भी लिख सकते हैं।

    मुझे यह जानकर उत्सुकता होगी कि सबसे तेज़ क्या हो जाता है।

  • +0

    'numVowels' को घटाया जा सकता है:' योग (x में शब्द के लिए स्वरों में x) ', क्योंकि इस शब्द के केवल एक ही पुनरावृत्ति की आवश्यकता होती है, जबकि'str.count' के परिणामस्वरूप 5 पुनरावृत्तियों का परिणाम होगा। –

    +0

    @ अश्विनी चौधरी अच्छी बात, मैंने आपकी पहली टिप्पणी को दर्शाने के लिए अपना जवाब संपादित किया। –

    +0

    'लेन (एक्स में x के लिए x यदि x 'aeiou' में x) 'काम नहीं करेगा - genexps की लंबाई नहीं है। आपको एक listcomp या 'sum (1 के लिए ..)' आदि या कुछ करने की आवश्यकता होगी। – DSM

    4

    चूंकि आप केवल प्रत्येक शब्द में स्वरों के अनुपात के साथ चिंतित हैं, तो आप पहले सभी स्वरों को a से प्रतिस्थापित कर सकते हैं। अब आप कुछ चीजों को आजमा सकते हैं जो तेजी से हो सकते हैं:

    • आप प्रत्येक चरण में पांच की बजाय एक अक्षर के लिए परीक्षण कर रहे हैं। यह तेजी से होना बाध्य है।
    • आप पूरी सूची को सॉर्ट करने और उन बिंदुओं की खोज करने में सक्षम हो सकते हैं जहां आप स्वर से जाते हैं (अब स्पष्ट रूप से a के रूप में स्पष्ट रूप से प्रतिनिधित्व करते हैं) गैर-स्वर में। यह एक वृक्ष संरचना है। शब्द में अक्षरों की संख्या पेड़ का स्तर है। स्वरों की संख्या बाएं शाखाओं की संख्या है।
    +0

    अन्य अक्षरों के साथ अक्षरों को बदलने का समय लागत है ... सॉर्टिंग के साथ ही। वास्तव में इन सभी विचारों को समय देना अच्छा लगेगा। – piokuc

    +1

    यह सच है। मैं उम्मीद करता हूं कि अंतर्निर्मित खोज/प्रतिस्थापन बहुत कुशल होगा, और यह लूप निष्पादन को 80% तक कम करेगा। (मैं अब दुर्भाग्य से सत्यापित करने की स्थिति में नहीं हूं।) – John

    +2

    मुझे लगता है कि यह उत्तर सबसे उपयोगी होगा, लेकिन पाइथन के बाहर पत्र प्रतिस्थापन करें। 'बिल्ली शब्दसूची | tr aeiou a | tr qwrtpsdfghjklzxcvbnm b> new_wordlist' और उसके बाद प्रक्रिया करें। – JosefAssad

    0
    for word in wordlist: 
        numVowels = 0 
        for letter in VOWELS: 
         numVowels += word.count(letter) 
        ratios.append(numVowels/float(len(word))) 
    

    कम निर्णय लेने, कम समय मतलब यह होना चाहिए, यह भी बातें, जो मुझे विश्वास तेजी से काम में बनाया का उपयोग करता है।

    1

    स्वरों की सूची से मेल खाने के लिए नियमित अभिव्यक्ति का उपयोग करें और मैचों की संख्या गिनें।

    >>> import re 
    >>> s = 'supercalifragilisticexpialidocious' 
    >>> len(re.findall('[aeiou]', s)) 
    16 
    
    +1

    नियमित अभिव्यक्तियों की संभावना अधिक है। मुझे नहीं लगता कि 'पुनः मिलान करने वाला इंजन अपने प्रारंभिक समाधान के साथ भी प्रतिस्पर्धा करने के लिए पर्याप्त तेज़ है। –

    +0

    +1 (आपको आधिकारिक तौर पर 100k से अधिक धक्का दे रहा है)। बधाई। – John

    +0

    @ जॉन, धन्यवाद! –

    0
    import timeit 
    
    words = 'This is a test string' 
    
    def vowelProportions(words): 
        counts, vowels = {}, 'aeiou' 
        wordLst = words.lower().split() 
        for word in wordLst: 
         counts[word] = float(sum(word.count(v) for v in vowels))/len(word) 
        return counts 
    
    def f(): 
        return vowelProportions(words) 
    
    print timeit.timeit(stmt = f, number = 17400) # 5 (len of words) * 17400 = 87,000 
    # 0.838676 
    
    0

    यहाँ कैसे लिनक्स पर एक कमांड लाइन के साथ यह गणना करने के लिए है: -

    cat wordlist.txt | tr -d aeiouAEIOU | paste - wordlist.txt | gawk '{ FS="\t"; RATIO = length($1)/ length($2); print $2, RATIO }'

    आउटपुट:

    aa 0 
    ab 0.5 
    abs 0.666667 
    

    नोट: wordlist.txt की प्रत्येक पंक्ति एक शब्द है । रिक्त लाइन शून्य त्रुटि

    +0

    पायथन के साथ, यह अधिक जटिल है, इसे पाइप करें: '| पायथन-सी "आयात sys; tmp = lambda x: sys.stdout.write (x.split ('\ t') [1] + str (float (len (x.split ('\ t') [0]))/फ्लोट (लेन (x.split ('\ t') [1]) - 1)) + '\ n'); मानचित्र (tmp, sys.stdin); " –