2009-07-21 13 views
11

में मैं वस्तुओं की क्रमबद्ध सूचियों का एक समूह है, और एक तुलना समारोहमर्ज अनुसार क्रमबद्ध सूचियों अजगर

class Obj : 
    def __init__(p) : 
     self.points = p 
def cmp(a, b) : 
    return a.points < b.points 

a = [Obj(1), Obj(3), Obj(8), ...] 
b = [Obj(1), Obj(2), Obj(3), ...] 
c = [Obj(100), Obj(300), Obj(800), ...] 

result = magic(a, b, c) 
assert result == [Obj(1), Obj(1), Obj(2), Obj(3), Obj(3), Obj(8), ...] 

कैसा magic नज़र करता है? मेरा वर्तमान कार्यान्वयन

def magic(*args) : 
    r = [] 
    for a in args : r += a 
    return sorted(r, cmp) 

लेकिन यह काफी अक्षम है। बेहतर जवाब?

+0

क्या ए, बी, सी क्रमबद्ध हैं? – Drakosha

+1

यदि वे हैं: http://stackoverflow.com/questions/464342/combining-two-sorted-lists-in-python – Drakosha

+0

उन सूचियां कितनी बड़ी हैं? उन्हें सॉर्ट करने में कितना समय बिताया जाता है? पहले अनुकूलित करें (और बाद में) आप अनुकूलित करें। –

उत्तर

13

अजगर मानक पुस्तकालय इसके लिए एक विधि प्रदान करता है: heapq.merge
दस्तावेज़ीकरण के अनुसार, यह itertools (लेकिन अधिक सीमाओं के साथ) का उपयोग करने के समान है; अगर आप उन सीमाओं के साथ नहीं रह सकते (या यदि आप अजगर 2.6 का उपयोग नहीं करते) आप कुछ इस तरह कर सकते हैं:

sorted(itertools.chain(args), cmp) 

हालांकि, मुझे लगता है कि अपनी खुद की समाधान के रूप में एक ही जटिलता है, हालांकि iterators का उपयोग कर देना चाहिए कुछ काफी अच्छा अनुकूलन और गति में वृद्धि। एक सूची का उपयोग करने का

+1

सीएमपी के बजाए कुंजी का उपयोग करना पसंद किया जाना चाहिए (और shoudl तेज होना चाहिए)। Python3 में वैसे भी cmp पैरामीटर नहीं है। – Jiri

+2

दरअसल, मैं सिर्फ ओपी के समान प्रारूप का उपयोग कर रहा था, लेकिन आप बिल्कुल सही हैं और * कुंजी * * cmp * पर प्राथमिकता दी जानी चाहिए। –

+0

ठीक है, और ओपी का सीएमपी फ़ंक्शन गलत है और काम नहीं करता है।यदि आप हेपैक का उपयोग कर रहे हैं, तो आपको अपनी कक्षा में __lt__ इत्यादि प्रदान करना होगा या इसके बजाय अपने ढेर में टुपल (सॉर्टिंग कुंजी, ऑब्जेक्ट) का उपयोग करना होगा। – habnabit

0

मैं चाहे वह किसी भी तेज किया जाएगा पता नहीं है, लेकिन आप के साथ इसे आसान बनाने सकता है:

def GetObjKey(a): 
    return a.points 

return sorted(a + b + c, key=GetObjKey) 

तुम भी, बेशक, cmp बजाय key इस्तेमाल कर सकते हैं यदि आप पसंद करते हैं।

2

bisect मॉड्यूल का उपयोग करें। प्रलेखन से: "यह मॉड्यूल प्रत्येक सम्मिलन के बाद सूची को सॉर्ट किए बिना सॉर्ट किए गए क्रम में सूची बनाए रखने के लिए समर्थन प्रदान करता है।"

import bisect 

def magic(*args): 
    r = [] 
    for a in args: 
     for i in a: 
      bisect.insort(r, i) 
    return r 
2

इसके बजाय, आप उपयोग कर सकते हैं एक [ढेर] (http://en.wikipedia.org/wiki/Heap_(data_structure)

प्रविष्टि हे (लॉग (एन)) है, इसलिए विलय एक, बी और सी ओ हो जाएगा (एन (एन लॉग इन करें))

अजगर में, आप उपयोग कर सकते हैं heapq module

+0

+1: स्वाभाविक रूप से अक्षम में एक सूची को सॉर्ट करना: एक बेहतर संरचना का उपयोग करके सॉर्ट को रोकें। –

+0

@ एसएलॉट जैसे ... – OrganicPanda

+0

@ ऑर्गेनिक पांडा: क्या आपने जवाब पढ़ा था? यह कहता है कि 'हेपैक' सॉर्टिंग लागत को कम करता है। यह एक बेहतर संरचना है। इस पर भी विचार करें। तीन अलग संग्रह जमा करना मूर्खतापूर्ण लगता है। म्यूटेबल ऑब्जेक्ट्स के एक हैश को जमा क्यों न करें; यह अन्य स्रोतों से वस्तुओं द्वारा अद्यतन किया जा सकता है। अब "तुलना" मूक है क्योंकि वस्तुओं को बिना किसी सॉर्टिंग के एक दूसरे के साथ ठीक से जोड़ा जा सकता है। –

0

एक पंक्ति समाधान हल कर का उपयोग करते हुए:।।

def magic(*args): 
    return sorted(sum(args,[]), key: lambda x: x.points) 

IMO इस समाधान बहुत पठनीय है

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

import heapq 
def magic(*args): 
    h = [] 
    for a in args: 
    heapq.heappush(h,a) 
    return [i for i in heapq.heappop(h) 
+0

आपकी हेपैक विधि एक गड़बड़ है। आप अपनी वस्तुओं की बजाय पूरी सूचियों को दबा रहे हैं, और आप कुंजी को अनदेखा कर रहे हैं। हालांकि, एक लाइनर ठंडा है। – itsadok

+0

हाँ आप सही हैं, मैंने कुछ बार हेपैक का उपयोग किया है और मैंने इसका परीक्षण करने के लिए इसे कंसोल करने के लिए पेस्ट नहीं किया है। मेरी गलती, क्षमा करें। हालांकि अब मैं देखता हूं कि ओबज ऑब्जेक्ट को हेपैक के लिए "क्रमबद्ध" परिभाषित किया जाना चाहिए, क्योंकि आप हेपैक में cmp/key फ़ंक्शन निर्दिष्ट नहीं कर सकते हैं। – Jiri

+0

यह कोड एक गड़बड़ के आसपास है। दोनों स्निपेट में सिंटैक्स त्रुटियां होती हैं, और संक्षेप में सूचियों के लिए योग का उपयोग करना बहुत अक्षम है। उल्लेख नहीं है कि लैम्ब्डा को बदलने के लिए ऑपरेटर.एट्टरेटटर है। – habnabit

0

ये रहा:

def merge(*args): 
    import copy 
    def merge_lists(left, right): 
     result = [] 
     while left and right: 
      which_list = (left if left[0] <= right[0] else right) 
      result.append(which_list.pop(0)) 
     return result + left + right 
    lists = list(args) 
    while len(lists) > 1: 
     left, right = copy.copy(lists.pop(0)), copy.copy(lists.pop(0)) 
     result = merge_lists(left, right) 
     lists.append(result) 
    return lists.pop(0) 

इसे इस तरह कॉल::

merged_list = merge(a, b, c) 
for item in merged_list: 
    print item 

अच्छा उपाय के लिए, मैं सूचियों के लिए एक पूरी तरह से कामकाज मर्ज प्रकार (मेरी तरह here से रूपांतरित) आपके ओब्जे वर्ग में कुछ बदलावों में फेंक देगा:

class Obj(object): 
    def __init__(self, p) : 
     self.points = p 
    def __cmp__(self, b) : 
     return cmp(self.points, b.points) 
    def __str__(self): 
     return "%d" % self.points 
  • __init__()
  • करने के लिए वस्तु
  • पास self से निकाले जाते हैं __cmp__ बनाओ एक सदस्य समारोह
  • एक str() सदस्य समारोह स्ट्रिंग
2

मैं रॉबर्टो Liffredo का जवाब चाहते रूप Obj पेश करने के लिए जोड़ें। मुझे heapq.merge() के बारे में पता नहीं था। Hmmmph।

class Obj(object): 
    def __init__(self, p) : 
     self.points = p 
    def __cmp__(self, b) : 
     return cmp(self.points, b.points) 
    def __str__(self): 
     return "%d" % self.points 

a = [Obj(1), Obj(3), Obj(8)] 
b = [Obj(1), Obj(2), Obj(3)] 
c = [Obj(100), Obj(300), Obj(800)] 

import heapq 

sorted = [item for item in heapq.merge(a,b,c)] 
for item in sorted: 
    print item 

या::

यहाँ पूर्ण समाधान रॉबर्टो के नेतृत्व का उपयोग कर कैसा दिखता है

for item in heapq.merge(a,b,c): 
    print item 
0

मैं एक ऐसी ही प्रश्न पूछा और कुछ उत्कृष्ट जवाब मिला:

उस सवाल से सबसे अच्छा समाधान मर्ज एल्गोरिथ्म, जो तुम यहाँ के बारे में पढ़ सकते हैं के वेरिएंट हैं:

0

नीचे एक समारोह है कि हे (एन) की तुलना में चलाता है का एक उदाहरण है ।

आप इसे और बी इटरेटर बनाने और उन्हें बढ़ाने के द्वारा इसे तेज़ी से बना सकते हैं।

मैं बस दो बार 3 सूचियों विलय करने के लिए समारोह कहा जाता है:

def zip_sorted(a, b): 
    ''' 
    zips two iterables, assuming they are already sorted 
    ''' 
    i = 0 
    j = 0 
    result = [] 
    while i < len(a) and j < len(b): 
     if a[i] < b[j]: 
      result.append(a[i]) 
      i += 1 
     else: 
      result.append(b[j]) 
      j += 1 
    if i < len(a): 
     result.extend(a[i:]) 
    else: 
     result.extend(b[j:]) 
    return result 

def genSortedList(num,seed): 
    result = [] 
    for i in range(num): 
     result.append(i*seed) 
    return result 

if __name__ == '__main__': 
    a = genSortedList(10000,2.0) 
    b = genSortedList(6666,3.0) 
    c = genSortedList(5000,4.0) 
    d = zip_sorted(zip_sorted(a,b),c) 
    print d 

हालांकि, heapq.merge इस पद्धति का एक मिश्रण का उपयोग करता है और सभी सूचियों की वर्तमान तत्वों ढेर लगाना है, तो ज्यादा बेहतर प्रदर्शन करना चाहिए

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