2012-03-13 6 views
5

मैं वर्तमान में इस कोड का उपयोग:पायथन में एक सूची में उप-अनुक्रम के सभी उदाहरणों को कैसे प्रतिस्थापित करें?

 
""" Replace all occurrences of subsequence a with b in list l """ 
def replace_subsequence(l,a,b): 
    for i in range(len(l)): 
     if(l[i:i+len(a)] == a): 
      l[i:i+len(a)] = b 
 

उदाहरण:

>>> l = [1,2,3] 
>>> replace_subsequence(l,[2,3],[4]) 
>>> l 
[1, 4] 

वहाँ यह करने के लिए एक अधिक कुशल और/या सुरुचिपूर्ण रास्ता नहीं है?

+0

'मैं के लिए रेंज में (लेन (एल)): 'i में रेंज के लिए छोटा किया जा सकता है (लेन (एल) - लेन (ए)):' – eumiro

+0

निश्चित रूप से, लेकिन मैं स्मृति में सूची बनाने के तरीके के साथ और सोच रहा था प्रत्येक प्रतिस्थापन के लिए, लेकिन केवल अंत में। या शायद एक सी कार्यान्वयन भी। – Maarten

+0

डेटा ऑब्जेक्ट हमेशा 'int' होगा, मुझे लगता है? – moooeeeep

उत्तर

5

दक्षता में सुधार करने के लिए, जब किसी सूची में एक sublist के लिए खोज

कोड (credits)

def match(pattern, list): 
    matches = [] 
    m = len(list) 
    n = len(pattern) 

    rightMostIndexes = preprocessForBadCharacterShift(pattern) 

    alignedAt = 0 
    while alignedAt + (n - 1) < m: 

     for indexInPattern in xrange(n-1, -1, -1): 
      indexInlist = alignedAt + indexInPattern 
      x = list[indexInlist] 
      y = pattern[indexInPattern] 

      if indexInlist >= m: 
       break 

      if x != y: 

       r = rightMostIndexes.get(x) 

       if x not in rightMostIndexes: 
        alignedAt = indexInlist + 1 

       else: 
        shift = indexInlist - (alignedAt + r) 
        alignedAt += (shift > 0 and shift or alignedAt + 1) 

       break 
      elif indexInPattern == 0: 
       matches.append(alignedAt) 
       alignedAt += 1 


    return matches 

def preprocessForBadCharacterShift(pattern): 
    map = { } 
    for i in xrange(len(pattern)-1, -1, -1): 
     c = pattern[i] 
     if c not in map: 
      map[c] = i 

    return map 

if __name__ == "__main__": 
    matches = match("ana", "bananas") 
    for integer in matches: 
     print "Match at:", integer 
    print (matches == [1, 3] and "OK" or "Failed") 

    matches = match([1, 2, 3], [0, 1, 2,3 , 4, 5, 6]) 
    for integer in matches: 
     print "list Match at:", integer 
    print (matches) 
0

xrange एक सरल सुधार है कि अपने कोड तेज़ हो जाएगी का उपयोग करना है आप Boyer–Moore string search algorithm उपयोग कर सकते हैं। xrange जनरेटर लौटाता है, इसलिए प्रदर्शन सुधार लंबे सूचियों के लिए कणों के लिए ध्यान देने योग्य होगा। लेकिन यहां तक ​​कि आपके वास्तव में छोटे परीक्षण कोड के साथ भी मुझे एक सभ्य वृद्धि मिलती है।

का उपयोग timeit:

replace_subsequence  0.337936162949, 100000 runs 
replace_subsequence_xrange 0.275990962982, 100000 runs 

इसके अतिरिक्त आपको लूप से len(a) बाहर, इस तरह से आप len() समारोह बुला रखने नहीं होगा करने के लिए एक चर आवंटित करने चाहिए। इससे एक महत्वपूर्ण गति भी मिल जाएगी।

1

यह निश्चित रूप से सुंदर नहीं है, लेकिन अगर तार को बदलने और string.replace का उपयोग कर बेहतर प्रदर्शन करेंगे यदि आपका डेटा उदाहरण के रूप में के रूप में सरल है मैं सोच रहा हूँ ...

def strx(l): 
    return str(l).strip('[]') 

def replace_substring(l, a, b): 
    return strx(l).replace(strx(a), strx(b)).split(', ') 
+0

केवल तभी यदि आप एक अद्वितीय चरित्र के रूप में प्रत्येक संभावित सूची तत्व को विश्वसनीय रूप से एन्कोड कर सकते हैं। –

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