2012-11-02 9 views
5

आदेश को संरक्षित करते समय सूची में डुप्लिकेट को हटाने के लिए नीचे एक सरल कार्य है। मैंने कोशिश की है और यह वास्तव में काम करता है, इसलिए यहां समस्या मेरी समझ है। ऐसा लगता है कि दूसरी बार जब आप किसी दिए गए आइटम के लिए uniq.remove(item) चलाते हैं, तो यह एक त्रुटि (KeyError या ValueError मुझे लगता है?) क्योंकि उस आइटम को अद्वितीय सेट से पहले ही हटा दिया गया है। क्या यह मामला नही है?मुझे लगता है कि यह एक त्रुटि उठाना चाहिए, लेकिन यह

def unique(seq): 
    uniq = set(seq) 
    return [item for item in seq if item in uniq and not uniq.remove(item)] 
+0

मैं वास्तव में इस कोड की तरह =) – katrielalex

+5

@katrielalex -- मैं नही। किसी संग्रह से निकालने और आइटम के दुष्प्रभाव के लिए एक शर्त का उपयोग करने से भ्रमित, कोड पढ़ने में कठिनाई होती है। (आईएमएचओ) – mgilson

+1

प्लस आप एक पूरी नई 'सेट' बना रहे हैं और सूची में फ़िल्टर के रूप में कार्य करने के लिए बस से प्रत्येक आइटम पॉप अप कर रहे हैं। मैं कल्पना नहीं कर सकता कि यह तेज़ है, और यह निश्चित रूप से स्पष्ट नहीं है, एक एकल पास (एक नई डी-डुप्लीड सूची बनाने के लिए) या डबल पास (सूची में डी-डुप्लींग के लिए) 'लूप के लिए । –

उत्तर

9

एक चेक if item in uniq जो पहले आइटम निकाल दिया जाता है निष्पादित हो जाता है नहीं है। and ऑपरेटर अच्छा है कि यह "शॉर्ट सर्किट" है। इसका मतलब यह है कि यदि बाईं ओर की स्थिति False के समान होती है, तो दाईं ओर की स्थिति का मूल्यांकन नहीं होता है - हम पहले से ही जानते हैं कि अभिव्यक्ति True जैसी नहीं हो सकती है।

+0

इसके लिए बहुत बहुत धन्यवाद। Uniq.remove (आइटम) वापस क्या मूल्य है? मैं पूरी अनुमान लगा रहा हूं "और uniq.remove (item)" पूरी चीज को लूप के लिए बदलने की बजाय सूची समझ में विधियों को चलाने का एक तरीका है, लेकिन मुझे यकीन नहीं है कि क्यों, उदाहरण के लिए, हम इसका उपयोग करते हैं "और नहीं" इस मामले में बस "और" के बजाय। संभवतः बी/सी अद्वितीय .remove (आइटम) कोई नहीं या गलत? – user1794459

+0

'uniq.remove (आइटम) 'रिटर्न' कोई नहीं '। 'कोई भी नहीं' 'सत्य' देता है। – mgilson

0
def unique_with_order(seq): 
    final = [] 
    for item in seq: 
     if item not in final: 
      final.append(item) 
    return final 


print unique_with_order([1,2,3,3,4,3,6]) 

इसे तोड़ें, इसे सरल बनाएं :) इन दिनों सब कुछ एक सूची समझ नहीं है।

+1

बेशक, सबकुछ नहीं! क्योंकि हमारे पास श्रद्धात्मक समझ और जनरेटर की समझ है :) – Kos

+1

हम करते हैं! लेकिन कभी-कभी एक अच्छा पुराने फैशन लूप बस ठीक है! –

+1

मुझे इस सूची में अनूठी सूची बनाने के तरीके के साथ कोई समस्या नहीं है - हालांकि मुझे नहीं लगता कि यह वास्तव में अभिव्यक्ति के बारे में वैचारिक समझ के साथ ओपी की मदद करता है। – mgilson

-1

पहली बार जब आप इस फ़ंक्शन को चलाते हैं, तो आपको अपनी सूची समझ से [1,2,3,4] मिल जाएगा और सेट uniq खाली हो जाएगा। दूसरी बार जब आप इस फ़ंक्शन को चलाते हैं, तो आपको [] मिलेगा क्योंकि आपका सेट uniq खाली होगा। दूसरे रन पर आपको कोई त्रुटि नहीं मिलने का कारण यह है कि पायथन का and शॉर्ट सर्किट - यह पहला खंड (item in uniq) झूठा है और दूसरा खंड चलाने के लिए परेशान नहीं है।

+0

मुझे डाउनवोट के लिए खेद है, लेकिन यह स्पष्ट नहीं है। दूसरी बार जब आप फ़ंक्शन चलाते हैं तो आपको क्या मतलब होगा आपको '[] 'मिलेगा? सेट 'uniq' खाली क्यों होगा? – mgilson

+0

'uniq' खाली है क्योंकि' uniq.remove (item) 'इसे खाली कर देता है। सूची समझ पहली बार शॉर्ट सर्किट नहीं करता है। मैं इसका जवाब लिखने के लिए अपना जवाब संपादित करूंगा। – dshapiro

+0

'uniq' हर बार फ़ंक्शन को 'uniq = set (seq)' – mgilson

4

set.remove एक इन-प्लेस ऑपरेशन है। इसका मतलब है कि यह कुछ भी वापस नहीं करता है (ठीक है, यह None देता है); और bool(None)False है।

तो अपनी सूची समझ प्रभावी रूप से है यह:

answer = [] 
for item in seq: 
    if item in uniq and not uniq.remove(item): 
     answer.append(item) 

और के बाद से अजगर सशर्त से कम सर्किटिंग (के रूप में अन्य लोगों ने बताया है) करता है, यह प्रभावी रूप से है:

answer = [] 
for item in seq: 
    if item in uniq: 
     if not uniq.remove(item): 
      answer.append(item) 
बेशक

, के बाद से unique.remove(item)None लौटाता है (bool जिसमें से False है), दोनों स्थितियों का मूल्यांकन किया जाता है या न ही।

uniq से item को हटाने का कारण यह है कि दूसरी स्थिति मौजूद है। इस तरह, अगर आपको item फिर से सामना करना पड़ता है (seq में डुप्लिकेट के रूप में), यह uniq में नहीं मिलेगा क्योंकि इसे पिछली बार वहां मिले uniq से हटा दिया गया था।

अब ध्यान रखें, यह काफी खतरनाक है क्योंकि वेरिएबल्स को संशोधित करने वाली स्थितियों को खराब शैली माना जाता है (जब आप पूरी तरह से परिचित नहीं होते हैं तो इस तरह के एक सशर्त डिबगिंग की कल्पना करें)। कंडीशनरों को वास्तव में उन चरों को संशोधित नहीं करना चाहिए जिन्हें वे चेक करते हैं। इस प्रकार, उन्हें केवल वेरिएबल पढ़ना चाहिए, उन्हें भी नहीं लिखना चाहिए।

आशा इस मदद करता है

+0

"दूसरी स्थिति का मुख्य कारण ..." -> "** ** ** दूसरी स्थिति के लिए कारण ...": डी। यह इंगित करने लायक हो सकता है कि कुछ इस तरह के दुष्प्रभावों के लिए शर्तों का उपयोग करने के लिए थोड़ा कठोर मानते हैं। – mgilson

+0

@ मिगिलसन: विधिवत नोट किया गया! उत्तर अपडेट किया गया :) – inspectorG4dget

+0

बहुत स्पष्ट प्रतिक्रिया, धन्यवाद। – user1794459

0

@ mgilson के जवाब सही एक है, लेकिन यहाँ, आपकी जानकारी के लिए, एक संभव आलसी (generator) एक ही समारोह का संस्करण है। इसका अर्थ यह है कि यह उन पुनरावृत्तियों के लिए काम करेगा जो स्मृति में फिट नहीं होते हैं - अनंत इटरेटर्स सहित - जब तक इसके तत्वों का सेट होगा।

def unique(iterable): 
    uniq = set() 
    for item in iterable: 
     if item not in uniq: 
      uniq.add(item) 
      yield item 
1

mgilson और अन्य ने सामान्य रूप से इस सवाल का जवाब दिया है। मैंने सोचा कि मैं बाहर बिंदु हो सकता है शायद अजगर में यह कर, अर्थात् itertools किए गए दस्तावेज़ों की recipe section से unique_everseen नुस्खा का उपयोग करने का विहित रास्ता है, नीचे उद्धृत:

from itertools import ifilterfalse 

def unique_everseen(iterable, key=None): 
    "List unique elements, preserving order. Remember all elements ever seen." 
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D 
    # unique_everseen('ABBCcAD', str.lower) --> A B C D 
    seen = set() 
    seen_add = seen.add 
    if key is None: 
     for element in ifilterfalse(seen.__contains__, iterable): 
      seen_add(element) 
      yield element 
    else: 
     for element in iterable: 
      k = key(element) 
      if k not in seen: 
       seen_add(k) 
       yield element 
संबंधित मुद्दे