सूचियों में डुप्लिकेट निकालना


995

बहुत ज्यादा मुझे यह देखने के लिए एक कार्यक्रम लिखने की ज़रूरत है कि क्या किसी सूची में कोई डुप्लिकेट है और अगर यह ऐसा करता है तो उन्हें हटा देता है और उन वस्तुओं के साथ एक नई सूची देता है जो डुप्लिकेट / हटाए नहीं गए थे। यह वही है जो मेरे पास है लेकिन ईमानदार होने के लिए मुझे नहीं पता कि मुझे क्या करना है।

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t

22
आपका विवरण कहता है कि आप डुप्लिकेट के लिए "एक सूची" की जांच करते हैं, लेकिन आपका कोड दो सूचियों की जांच करता है।
ब्रेंडन लॉन्ग


* सेट का उपयोग: शब्दकोश का उपयोग कर सूची (सेट (ELEMENTS_LIST)) *: सूची (dict.fromkeys (ELEMENTS_LIST))
शायन अमानी

जवाबों:


1640

वस्तुओं का एक अनूठा संग्रह प्राप्त करने के लिए आम दृष्टिकोण एक का उपयोग करना है set। सेट अलग-अलग वस्तुओं के अनियोजित संग्रह हैं। किसी भी चलने योग्य से एक सेट बनाने के लिए, आप इसे बिल्ट-इन फ़ंक्शन को पास कर सकते हैं । यदि आपको बाद में फिर से एक वास्तविक सूची की आवश्यकता है, तो आप सेट को फ़ंक्शन में पास कर सकते हैं ।set()list()

निम्नलिखित उदाहरण को कवर करना चाहिए जो आप करने की कोशिश कर रहे हैं:

>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]

जैसा कि आप उदाहरण के परिणाम से देख सकते हैं, मूल आदेश कायम नहीं है । जैसा कि ऊपर उल्लेख किया गया है, सेट स्वयं अनियोजित संग्रह हैं, इसलिए ऑर्डर खो गया है। किसी सूची में सेट को परिवर्तित करते समय, एक मनमाना क्रम बनाया जाता है।

व्यवस्था बनाए रखना

यदि आदेश आपके लिए महत्वपूर्ण है, तो आपको एक अलग तंत्र का उपयोग करना होगा। इसके लिए एक बहुत ही सामान्य समाधान OrderedDictप्रविष्टि के दौरान कुंजियों के क्रम को बनाए रखने के लिए भरोसा करना है:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

पायथन 3.7 के साथ शुरू , अंतर्निर्मित शब्दकोश को प्रविष्टि क्रम को बनाए रखने की गारंटी है, इसलिए आप इसका उपयोग सीधे भी कर सकते हैं यदि आप Python 3.7 या बाद में (या CPython 3.6):

>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

ध्यान दें कि पहले एक शब्दकोश बनाने और फिर उससे एक सूची बनाने के कुछ ओवरहेड हो सकते हैं। यदि आपको वास्तव में ऑर्डर को संरक्षित करने की आवश्यकता नहीं है, तो आप अक्सर सेट का उपयोग करके बेहतर होते हैं, खासकर क्योंकि यह आपको काम करने के लिए बहुत अधिक संचालन देता है। की जाँच करें इस सवाल का अधिक जानकारी और वैकल्पिक तरीकों जब डुप्लिकेट हटाने क्रम बनाए रखने के लिए।


अंत में ध्यान दें कि दोनों के setसाथ-साथ OrderedDict/ dictसमाधान के लिए आपके आइटम को हैशेबल होना चाहिए । इसका आमतौर पर मतलब है कि उन्हें अपरिवर्तनीय होना चाहिए। यदि आपको उन वस्तुओं से निपटना है जो कि धोने योग्य नहीं हैं (जैसे सूची ऑब्जेक्ट), तो आपको एक धीमे दृष्टिकोण का उपयोग करना होगा जिसमें आपको मूल रूप से प्रत्येक आइटम की आवश्यकता प्रत्येक नेस्टेड लूप में तुलना करनी होगी।


4
यह अस्वास्थ्यकर सूची तत्वों (उदाहरणों की सूची) के लिए काम नहीं करता है
केएनजेड

3
@KNejad यही आखिरी पैराग्राफ है।
प्रहार

ओह उफ़। पूरी बात पढ़नी चाहिए थी। मैंने जो किया, वह सूचियों के बजाय टुपल्स का उपयोग कर रहा था ताकि यह दृष्टिकोण अभी भी काम कर सके।
KNejad

इसे उदाहरण में जोड़ें, t = [3, 2, 1, 1, 2, 5, 6, 7, 8], अंतर स्पष्ट रूप से दिखाता है!
सेलफिश009

"... पहले एक शब्दकोश बनाने का ओवरहेड ... यदि आपको वास्तव में ऑर्डर को संरक्षित करने की आवश्यकता नहीं है, तो आप एक सेट का उपयोग करके बेहतर हैं।" - मैंने इसे प्रोफाइल किया क्योंकि मैं उत्सुक था अगर यह वास्तव में सच था। मेरे समय से पता चलता है कि वास्तव में सेट थोड़ा तेज है: 1.12 sets प्रति लूप (सेट) बनाम 1.53 overs प्रति लूप (तानाशाही) 1M लूप से अधिक 1 एम पुनरावृत्तियों के बारे में 4 जी के पूर्ण समय अंतर के साथ। इसलिए यदि आप एक तंग आंतरिक पाश में यह कर रहे हैं तो आप देखभाल कर सकते हैं, अन्यथा शायद नहीं।
मिलरदेव 13

414

पायथन 2.7 में, मूल क्रम में रखते हुए पुनरावृत्तियों को डुप्लिकेट से निकालने का नया तरीका है:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

पायथन 3.5 में , ऑर्डरडीडक्ट का सी कार्यान्वयन है। मेरी टाइमिंग बताती है कि यह अब पायथन 3.5 के लिए विभिन्न दृष्टिकोणों में सबसे तेज और सबसे छोटा है।

पायथन 3.6 में , नियमित रूप से तानाशाह आदेश और कॉम्पैक्ट दोनों बन गया। (यह सुविधा CPython और PyPy के लिए है, लेकिन अन्य कार्यान्वयन में मौजूद नहीं हो सकती है)। यह हमें आदेश को बनाए रखते हुए कटौती करने का एक नया सबसे तेज़ तरीका देता है:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

पायथॉन 3.7 में , सभी आदेशों पर आदेश दिए गए दोनों के लिए नियमित रूप से तानाशाही की गारंटी है। तो, सबसे छोटा और सबसे तेज़ समाधान है:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

10
मुझे लगता है कि वस्तुओं को क्रम में रखने का यही एकमात्र तरीका है।
हर्बर्ट अमरल


5
@MartijnPieters सही करना: मुझे लगता है कि वस्तुओं को क्रम में रखने का यह एकमात्र सरल तरीका है।
हर्बर्ट अमल

11
इसके लिए भी, मूल सूची की सामग्री धुलाई योग्य होनी चाहिए
Davide

जैसा कि @Davide ने उल्लेख किया है, मूल सूची को धो सकते हैं। इसका मतलब है, कि यह शब्दकोशों की सूची के लिए काम नहीं करता है। TypeError: unhashable type: 'dictlist'
क्रेज

186

यह वन-लाइनर है: list(set(source_list)) चाल चलेगा।

set कुछ ऐसा है जो संभवतः डुप्लिकेट नहीं कर सकता है।

अद्यतन: एक ऑर्डर-प्रोटेक्शन अप्रोच दो लाइनें है:

from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()

यहां हम इस तथ्य का उपयोग करते हैं कि OrderedDictकुंजियों के सम्मिलन क्रम को याद रखता है, और जब किसी विशेष कुंजी पर एक मूल्य अपडेट किया जाता है, तो इसे नहीं बदलता है। हम Trueमूल्यों के रूप में सम्मिलित करते हैं, लेकिन हम कुछ भी सम्मिलित कर सकते हैं, मूल्यों का उपयोग नहीं किया जाता है। ( उपेक्षित मूल्यों के साथ भी setबहुत कुछ काम करता dictहै।)


4
यह केवल काम करता है अगर source_listधो सकते हैं।
एड्रियन कीस्टर

@ एड्रियनकेस्टर: यह सच है। ऐसी वस्तुएं हैं जिनमें उचित समानता शब्दार्थ हैं, लेकिन वे धोने योग्य नहीं हैं, उदाहरण के लिए सूची। OTOH अगर हमारे पास जल्दबाजी जैसा शॉर्टकट नहीं हो सकता है, तो हम वर्तमान में ज्ञात सभी अद्वितीय तत्वों के साथ हर तत्व की तुलना करते हुए एक द्विघात एल्गोरिथ्म को समाप्त करते हैं। यह शॉर्ट इनपुट के लिए पूरी तरह से ठीक हो सकता है, खासकर बहुत सारे डुप्लिकेट के साथ।
9000

सही, बिल्कुल। मुझे लगता है कि यदि आप इस सामान्य उपयोग के मामले को ध्यान में रखते हैं तो आपका उत्तर उच्च गुणवत्ता वाला होगा।
एड्रियन कीस्टर

94
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> s = []
>>> for i in t:
       if i not in s:
          s.append(i)
>>> s
[1, 2, 3, 5, 6, 7, 8]

33
ध्यान दें कि यह विधि O (n ^ 2) समय में काम करती है और इस प्रकार बड़ी सूचियों पर बहुत धीमी है।
14

@ क्रिस_ सैंड्स: सुनिश्चित नहीं है कि frozensetगैर-धोने योग्य सामग्री के साथ काम करता है। मैं अभी भी गैर hashable त्रुटि का उपयोग करते समय हो रही है frozenset
एड्रियन कीस्टर

85

यदि आपको आदेश की परवाह नहीं है, तो बस यह करें:

def remove_duplicates(l):
    return list(set(l))

A setको डुप्लिकेट नहीं होने की गारंटी है।


3
तब तक काम नहीं करता जब तक कि lवह धोने योग्य न हो।
एड्रियन कीस्टर

41

डुप्लिकेट के पहले तत्वों के क्रम को बनाए रखते हुए एक नई सूची बनाना L

newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]

उदाहरण के लिए if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]तब newlistहोगा[1,2,3,4,5]

यह जाँचता है कि प्रत्येक नया तत्व जोड़ने से पहले सूची में पहले दिखाई नहीं दिया है। साथ ही इसे आयात की भी जरूरत नहीं है।


3
इसमें O (n ^ 2) की समय जटिलता है । के साथ जवाब setऔर OrderedDictकम परिमित समय जटिलता हो सकती है।
ब्लबरडाइब्लूब

मैंने अपने कोड में इस समाधान का उपयोग किया और महान काम किया, लेकिन मुझे लगता है कि यह समय लेने वाला है
गेरासिमोस राग्वानिस

@blubberdiblub आपको बता सकता है कि सेट में और अधिक कुशल कोड क्या मौजूद है और ऑर्डरडीडक्ट जो उन्हें कम समय लेने वाला बना सकता है? (उन्हें लोड करने के ओवरहेड को छोड़कर)
ilias iliadis

के सामान्य कार्यान्वयन @iliasiliadis सेट और dict उपयोग हैश या पेड़ों (संतुलित के कुछ फार्म)। आपको सेट या तानाशाही बनाने और उसमें (कई बार) खोज करने पर विचार करना होगा , लेकिन उनकी परिमित जटिलता आमतौर पर ओ (n ^ 2) से कम होती है । सरल शब्दों में "प्रवर्धित" का अर्थ है औसत (वे औसत मामले की तुलना में उच्च जटिलता के साथ सबसे खराब मामले हो सकते हैं)। यह तभी प्रासंगिक है जब आपके पास बड़ी संख्या में आइटम हों।
ब्लबरडाइब्लूब

25

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

def ordered_set(in_list):
    out_list = []
    added = set()
    for val in in_list:
        if not val in added:
            out_list.append(val)
            added.add(val)
    return out_list

दक्षता की तुलना करने के लिए, मैंने 100 पूर्णांक के यादृच्छिक नमूने का उपयोग किया - 62 अद्वितीय थे

from random import randint
x = [randint(0,100) for _ in xrange(100)]

In [131]: len(set(x))
Out[131]: 62

यहाँ माप के परिणाम हैं

In [129]: %timeit list(OrderedDict.fromkeys(x))
10000 loops, best of 3: 86.4 us per loop

In [130]: %timeit ordered_set(x)
100000 loops, best of 3: 15.1 us per loop

ठीक है, अगर सेट को समाधान से हटा दिया जाता है तो क्या होता है?

def ordered_set(inlist):
    out_list = []
    for val in inlist:
        if not val in out_list:
            out_list.append(val)
    return out_list

परिणाम ऑर्डरडीक के साथ उतना बुरा नहीं है , लेकिन अभी भी मूल समाधान के 3 गुना से अधिक है

In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop

लूप की तुलना में तेजी लाने के लिए सेट लुकअप का उपयोग करते हुए अच्छा लगा। यदि आदेश सूची (सेट (x)) से अभी भी 6x अधिक तेज नहीं है
जोप सेप

@ जो, मेरे सहयोगी के लिए यह मेरा पहला सवाल था - आदेश मायने रखता है; अन्यथा, यह तुच्छ मुद्दा होता
ज्वालामुखी

अनुकूलित सेट का अनुकूलित संस्करण, जो भी रुचि रखता है के लिए def unique(iterable)::; seen = set(); seen_add = seen.add; return [item for item in iterable if not item in seen and not seen_add(item)]
DrD

25

पंडों और Numpy का उपयोग कर समाधान भी हैं। .tolist()यदि आप एक सूची चाहते हैं, तो आपको दोनों का उपयोग करना होगा।

t=['a','a','b','b','b','c','c','c']
t2= ['c','c','b','b','b','a','a','a']

पंडों का हल

पंडों समारोह का उपयोग unique():

import pandas as pd
pd.unique(t).tolist()
>>>['a','b','c']
pd.unique(t2).tolist()
>>>['c','b','a']

नम्र हल

संख्यात्मक कार्य का उपयोग करना unique()

import numpy as np
np.unique(t).tolist()
>>>['a','b','c']
np.unique(t2).tolist()
>>>['a','b','c']

ध्यान दें कि numpy.unique () भी मानों को क्रमबद्ध करता है । इसलिए सूची t2को वापस कर दिया गया है। यदि आप इस उत्तर में दिए गए आदेश का उपयोग करना चाहते हैं :

_, idx = np.unique(t2, return_index=True)
t2[np.sort(idx)].tolist()
>>>['c','b','a']

दूसरों की तुलना में समाधान इतना सुरुचिपूर्ण नहीं है, हालांकि, पंडों की तुलना में। प्राचीन (), numpy.unique () आपको यह जांचने की अनुमति देता है कि क्या नेस्टेड एरे एक चयनित अक्ष के साथ अद्वितीय हैं।


यह सूची को अफीम सरणी में बदल देगा जो गड़बड़ है और तार के लिए काम नहीं करेगा।
user227666

1
@ user227666 आपकी समीक्षा के लिए धन्यवाद, लेकिन यह सच नहीं है कि यह स्ट्रिंग के साथ भी काम करता है और आप .tolist जोड़ सकते हैं यदि आप एक सूची प्राप्त करना चाहते हैं ...
GM

1
मुझे लगता है कि यह थोड़े है जैसे कि एक मधुमक्खी को मारने की कोशिश कर रहा है। काम करता है, निश्चित! लेकिन, सिर्फ इस उद्देश्य के लिए पुस्तकालय का आयात करना थोड़ा भारी हो सकता है, नहीं?
देबोसमित रे

@DebosmitRay यह उपयोगी हो सकता है यदि आप डेटा साइंस में काम करते हैं, जहां आमतौर पर आप सुस्ता के साथ काम करते हैं और कई बार आपको सुन्न सरणी के साथ काम करने की आवश्यकता होती है।
जीएम

2020 @DebosmitRay मैं आशा है कि आप अपने मन और उपयोग numpy बदलने में सर्वश्रेष्ठ उत्तर / हर बार जब आप कर सकते हैं पांडा
अहं

21

करने का दूसरा तरीका:

>>> seq = [1,2,3,'a', 'a', 1,2]
>> dict.fromkeys(seq).keys()
['a', 1, 2, 3]

1
ध्यान दें कि आधुनिक पायथन संस्करणों में (2.7+ मुझे लगता है, लेकिन मैं निश्चित रूप से याद नहीं करता हूं), keys()एक शब्दकोश दृश्य वस्तु देता है, सूची नहीं।
डस्टिन वायट

16

सरल और आसान:

myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanlist = []
[cleanlist.append(x) for x in myList if x not in cleanlist]

आउटपुट:

>>> cleanlist 
[1, 2, 3, 5, 6, 7, 8]

5
फिर भी द्विघात जटिलता - inO (n) ऑपरेशन है और आपके cleanlistपास अधिकांश nसंख्याएँ होंगी => सबसे खराब स्थिति ~ O (n ^ 2)
jermenkoo

6
साइड इफेक्ट्स के लिए सूची समझ का उपयोग नहीं किया जाना चाहिए।
जीन फ़्राँस्वा Fabre

13

इस उत्तर में, दो खंड होंगे: दो अद्वितीय समाधान, और विशिष्ट समाधानों के लिए गति का एक ग्राफ।

डुप्लिकेट आइटम निकाल रहा है

इनमें से अधिकांश उत्तर केवल डुप्लिकेट आइटमों को हटाते हैं जो कि धोए जा सकने वाले आइटम हैं , लेकिन यह प्रश्न स्पष्ट नहीं है कि इसे केवल धोने योग्य वस्तुओं की आवश्यकता नहीं है , जिसका अर्थ है कि मैं कुछ समाधानों की पेशकश करूंगा, जिन्हें धोने योग्य वस्तुओं की आवश्यकता नहीं है ।

collection.Counter मानक पुस्तकालय में एक शक्तिशाली उपकरण है जो इसके लिए एकदम सही हो सकता है। केवल एक अन्य समाधान है जिसमें काउंटर भी है। हालाँकि, यह समाधान भी हैज़िकल कीज़ तक सीमित है ।

काउंटर में अस्वास्थ्यकर कुंजियों की अनुमति देने के लिए, मैंने एक कंटेनर क्लास बनाया, जो ऑब्जेक्ट के डिफ़ॉल्ट हैश फ़ंक्शन को प्राप्त करने का प्रयास करेगा, लेकिन यदि यह विफल हो जाता है, तो यह इसके पहचान फ़ंक्शन को आज़माएगा। यह एक eq और हैश विधि को भी परिभाषित करता है । यह हमारे समाधान में उपलब्ध वस्तुओं को अनुमति देने के लिए पर्याप्त होना चाहिए । धोने योग्य वस्तुओं का उपचार किया जाएगा जैसे कि वे धोने योग्य हों। हालांकि, यह हैश फ़ंक्शन अस्वास्थ्यकर वस्तुओं के लिए पहचान का उपयोग करता है, जिसका अर्थ है कि दो समान ऑब्जेक्ट जो दोनों उपलब्ध नहीं हैं, काम नहीं करेंगे। मेरा सुझाव है कि आप इसे ओवरराइड कर रहे हैं, और इसे बराबर म्यूटेबल प्रकार के हैश का उपयोग करने के लिए बदल रहे हैं (जैसे hash(tuple(my_list))यदि उपयोग कर रहे हैंmy_list एक सूची है )।

मैंने भी दो उपाय किए। एक और समाधान जो ऑर्डरडीडिक्ट और काउंटर दोनों के उपवर्ग का उपयोग करके वस्तुओं के ऑर्डर को रखता है, जिसे 'ऑर्डरेडकाउंटर' नाम दिया गया है। अब, यहाँ कार्य हैं:

from collections import OrderedDict, Counter

class Container:
    def __init__(self, obj):
        self.obj = obj
    def __eq__(self, obj):
        return self.obj == obj
    def __hash__(self):
        try:
            return hash(self.obj)
        except:
            return id(self.obj)

class OrderedCounter(Counter, OrderedDict):
     'Counter that remembers the order elements are first encountered'

     def __repr__(self):
         return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

     def __reduce__(self):
         return self.__class__, (OrderedDict(self),)

def remd(sequence):
    cnt = Counter()
    for x in sequence:
        cnt[Container(x)] += 1
    return [item.obj for item in cnt]

def oremd(sequence):
    cnt = OrderedCounter()
    for x in sequence:
        cnt[Container(x)] += 1
    return [item.obj for item in cnt]

रीमेड नॉन-ऑर्डर सॉर्टिंग है, ऑर्मर्ड को क्रमबद्ध करने का आदेश दिया गया है। आप स्पष्ट रूप से बता सकते हैं कि कौन सा तेज है, लेकिन मैं किसी भी तरह समझाऊंगा। गैर-क्रमबद्ध छंटाई थोड़ी तेज है। यह कम डेटा रखता है, क्योंकि इसे ऑर्डर की आवश्यकता नहीं है।

अब, मैं भी प्रत्येक उत्तर की गति तुलना दिखाना चाहता था। तो, मैं अभी करूँगा।

कौन सा फ़ंक्शन सबसे तेज़ है?

डुप्लिकेट को निकालने के लिए, मैंने कुछ उत्तरों से 10 फ़ंक्शन एकत्र किए। मैंने प्रत्येक फ़ंक्शन की गति की गणना की और इसे matplotlib.pyplot का उपयोग करके एक ग्राफ में डाला ।

मैंने इसे ग्राफिंग के तीन राउंड में विभाजित किया। एक धोने योग्य कोई भी वस्तु है, जिसे हैश किया जा सकता है, एक धोने योग्य कोई भी वस्तु है जिसे हैशेड नहीं किया जा सकता है। एक क्रमबद्ध अनुक्रम वह अनुक्रम है जो आदेश को संरक्षित करता है, एक अनियोजित अनुक्रम आदेश को संरक्षित नहीं करता है। अब, यहां कुछ और शब्द दिए गए हैं:

अक्रमित Hashable कोई भी तरीका जो डुप्लिकेट है, जो जरूरी आदेश रखने के लिए नहीं था हटा दिया था। इसमें अस्वस्थता के लिए काम नहीं करना था, लेकिन यह हो सकता है।

आदेश दिया Hashable किसी भी विधि है जो सूची में आइटम्स के आदेश रखा के लिए था, लेकिन यह unhashables के लिए काम करने के लिए नहीं था, लेकिन यह कर सकते थे।

अनहद का आदेश दिया कोई भी तरीका है जो सूची में वस्तुओं के क्रम को बनाए रखता है, और अनहैबल्स के लिए काम करता है।

Y- अक्ष पर सेकंड की मात्रा है।

X- अक्ष पर वह संख्या है जिस पर फ़ंक्शन को लागू किया गया था।

हमने असमान हैशबल्स के लिए अनुक्रम उत्पन्न किए और निम्नलिखित समझ के साथ हैशबल्स का आदेश दिया: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]

आदेशित अस्वस्थ के लिए: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]

ध्यान दें कि रेंज में एक 'स्टेप' है क्योंकि इसके बिना, यह तब तक 10x हो जाता है। अपने व्यक्तिगत विचार के कारण, मुझे लगा कि यह पढ़ने में थोड़ा आसान लग रहा है।

इस बात पर भी ध्यान दें कि किंवदंती क्या हैं, मैंने फ़ंक्शन के सबसे महत्वपूर्ण भागों के रूप में अनुमान लगाने की कोशिश की है। क्या कार्य सबसे खराब या सबसे अच्छा है? ग्राफ अपने लिए बोलता है।

उस बसे के साथ, यहाँ रेखांकन हैं।

अनियंत्रित हैशबल्स

यहां छवि विवरण दर्ज करें (ज़ूम इन) यहां छवि विवरण दर्ज करें

हशबेल को आदेश दिया

यहां छवि विवरण दर्ज करें (ज़ूम इन) यहां छवि विवरण दर्ज करें

अनहैबल्स का आदेश दिया

यहां छवि विवरण दर्ज करें (ज़ूम इन) यहां छवि विवरण दर्ज करें


11

मेरे पास मेरी सूची में एक तानाशाही थी, इसलिए मैं उपरोक्त दृष्टिकोण का उपयोग नहीं कर सका। मुझे त्रुटि मिली:

TypeError: unhashable type:

तो अगर आप के बारे में परवाह आदेश और / या कुछ आइटम हैं unhashable । तब आपको यह उपयोगी लग सकता है:

def make_unique(original_list):
    unique_list = []
    [unique_list.append(obj) for obj in original_list if obj not in unique_list]
    return unique_list

कुछ एक अच्छा समाधान नहीं होने के लिए साइड इफेक्ट के साथ सूची की समझ पर विचार कर सकते हैं। यहाँ एक विकल्प है:

def make_unique(original_list):
    unique_list = []
    map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
    return unique_list

6
mapएक साइड इफेक्ट के साथ एक सूची की तुलना में और भी अधिक भ्रामक है। इसके अलावा, lambda x: unique_list.append(x)बस एक गुच्छेदार और धीमा रास्ता है unique_list.append
अपहरण

तत्वों को सिर्फ एक पंक्ति में जोड़ने का बहुत उपयोगी तरीका, धन्यवाद!
ZLNK

2
@ZLNK कृपया, कभी भी इसका उपयोग न करें। वैचारिक रूप से बदसूरत होने के अलावा, यह भी बेहद अक्षम है, क्योंकि आप वास्तव में एक संभावित बड़ी सूची बनाते हैं और इसे केवल बुनियादी दबाव बनाने के लिए फेंक देते हैं।
एली कोरविगो

10

सभी आदेश-संरक्षण के दृष्टिकोण जो मैंने अब तक यहां देखे हैं, या तो भोली तुलना (ओ (एन ^ 2) के साथ सबसे अच्छी तरह से समय-जटिलता) या भारी-वजन OrderedDicts/ set+ listसंयोजनों का उपयोग करते हैं जो कि धोने योग्य इनपुट तक सीमित हैं। यहाँ एक हैश-स्वतंत्र ओ (हल) है:

अद्यतन ने keyतर्क, प्रलेखन और पायथन 3 संगतता को जोड़ा ।

# from functools import reduce <-- add this import on Python 3

def uniq(iterable, key=lambda x: x):
    """
    Remove duplicates from an iterable. Preserves order. 
    :type iterable: Iterable[Ord => A]
    :param iterable: an iterable of objects of any orderable type
    :type key: Callable[A] -> (Ord => B)
    :param key: optional argument; by default an item (A) is discarded 
    if another item (B), such that A == B, has already been encountered and taken. 
    If you provide a key, this condition changes to key(A) == key(B); the callable 
    must return orderable objects.
    """
    # Enumerate the list to restore order lately; reduce the sorted list; restore order
    def append_unique(acc, item):
        return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or acc 
    srt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1]))
    return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))] 

फिर भी, इस समाधान के लिए आदेश योग्य तत्वों की आवश्यकता है। मैं अपनी सूचियों की सूची को विशिष्ट बनाने के लिए इसका उपयोग करूंगा: यह tuple()सूचियों और उन्हें हैश करने के लिए एक दर्द है । | | | | - सामान्यतया, हैश प्रक्रिया पूरे डेटा के आकार के लिए आनुपातिक समय लेती है, जबकि यह समाधान केवल सूची की लंबाई के आधार पर, एक समय O (nlog (n)) लेता है।
लक्सैक्स

मुझे लगता है कि सेट-आधारित दृष्टिकोण समान रूप से सस्ता है (O (n log n)), या सस्ता है, जैसे कि uniques की पहचान करना। (यह दृष्टिकोण, हालांकि, बहुत बेहतर होगा।) यह भी प्रारंभिक आदेश को संरक्षित नहीं करता है, लेकिन यह एक पूर्वानुमान आदेश देता है।
9000

@ 9000 यह सच है। मैंने कभी भी हैश-टेबल-आधारित दृष्टिकोण की समय-जटिलता का उल्लेख नहीं किया है, जो स्पष्ट रूप से ओ (एन) है। यहाँ आप हैश-तालिकाओं को शामिल करते हुए कई उत्तर पा सकते हैं। वे सार्वभौमिक नहीं हैं, हालांकि, क्योंकि उन्हें वस्तुओं को धोने योग्य बनाने की आवश्यकता होती है। इसके अलावा, वे बहुत अधिक स्मृति-गहन हैं।
एली कोरविगो

इस उत्तर को पढ़ने और समझने का समय लेता है। जब आप सूचकांकों का उपयोग नहीं कर रहे हैं तो क्या गणना करने का कोई मतलब है? reduce() पहले से ही एक क्रमबद्ध संग्रह पर काम कर रहा है srt_enum, तुम क्यों लागू किया sortedफिर से?
ब्रायोनी

@Brayoni पहला सॉर्ट है जिसमें समान मानों को समूहित किया गया है, दूसरा क्रम प्रारंभिक क्रम को पुनर्स्थापित करने के लिए है। मूल सापेक्ष क्रम पर नज़र रखने के लिए गणना की आवश्यकता है।
एली कोरविगो

9

यदि आप ऑर्डर को संरक्षित करना चाहते हैं, और यहां किसी भी बाहरी मॉड्यूल का उपयोग नहीं करना है, तो ऐसा करने का एक आसान तरीका है:

>>> t = [1, 9, 2, 3, 4, 5, 3, 6, 7, 5, 8, 9]
>>> list(dict.fromkeys(t))
[1, 9, 2, 3, 4, 5, 6, 7, 8]

नोट: यह विधि उपस्थिति के क्रम को बनाए रखती है, इसलिए, जैसा कि ऊपर देखा गया है, नौ एक के बाद एक आएंगे क्योंकि यह पहली बार दिखाई दिया था। हालाँकि, यह वही परिणाम है जो आपको करने के साथ मिलेगा

from collections import OrderedDict
ulist=list(OrderedDict.fromkeys(l))

लेकिन यह बहुत छोटा है, और तेजी से चलता है।

यह काम करता है क्योंकि हर बार fromkeysफ़ंक्शन एक नई कुंजी बनाने की कोशिश करता है, अगर मूल्य पहले से मौजूद है तो यह बस इसे अधिलेखित कर देगा। यह अभिप्राय सभी शब्दकोश में प्रभावित करता है, क्योंकि fromkeysएक शब्दकोश है जहाँ सभी कुंजियों का मूल्य है None, इसलिए प्रभावी रूप से यह सभी डुप्लिकेट को इस तरह समाप्त कर देता है।


इसके अलावा इसे आज़माने यहाँ
vineeshvs

8

आप यह भी कर सकते हैं:

>>> t = [1, 2, 3, 3, 2, 4, 5, 6]
>>> s = [x for i, x in enumerate(t) if i == t.index(x)]
>>> s
[1, 2, 3, 4, 5, 6]

कारण है कि ऊपर काम करता है कि indexविधि एक तत्व का केवल पहला सूचकांक देता है। डुप्लिकेट तत्वों में उच्च सूचकांक होते हैं। यहाँ देखें :

list.index (x [, start [, end]]])
पहले आइटम की सूची में शून्य आधारित सूचकांक लौटाएं जिसका मान x है। यदि ऐसा कोई आइटम नहीं है, तो एक मान को बढ़ाता है।


यह बहुत ही अयोग्य है। list.indexएक रैखिक-समय ऑपरेशन है, जो आपके समाधान को द्विघात बनाता है।
एली कोरविगो

आप सही हे। लेकिन मैं यह भी मानता हूं कि यह स्पष्ट है कि समाधान एक ऐसा लाइनर होना है जो ऑर्डर को संरक्षित करे। बाकी सब कुछ पहले से ही यहाँ है।
एटोनल


7

संरक्षित करने के आदेश के साथ संस्करण को कम करें:

मान लें कि हमारे पास सूची है:

l = [5, 6, 6, 1, 1, 2, 2, 3, 4]

वैरिएंट (अक्षम) को कम करें:

>>> reduce(lambda r, v: v in r and r or r + [v], l, [])
[5, 6, 1, 2, 3, 4]

5 x तेज लेकिन अधिक परिष्कृत

>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]

स्पष्टीकरण:

default = (list(), set())
# user list to keep order
# use set to make lookup faster

def reducer(result, item):
    if item not in result[1]:
        result[0].append(item)
        result[1].add(item)
    return result

reduce(reducer, l, default)[0]

7

एक सूची से डुप्लिकेट को हटाने का सबसे अच्छा तरीका सेट () फ़ंक्शन का उपयोग कर रहा है , अजगर में उपलब्ध है, फिर से उस सूची में उस सेट को परिवर्तित करना

In [2]: some_list = ['a','a','v','v','v','c','c','d']
In [3]: list(set(some_list))
Out[3]: ['a', 'c', 'd', 'v']

@MeetZaveri खुश!
अनुराग मिश्रा

नई सूचियों और सेटों को त्वरित करना मुफ्त नहीं है। यदि हम इसे कई बार त्वरित उत्तराधिकार में करते हैं (यानी बहुत तंग पाश में), और सूची बहुत छोटी है?
Z4-tier

6

आप निम्न फ़ंक्शन का उपयोग कर सकते हैं:

def rem_dupes(dup_list): 
    yooneeks = [] 
    for elem in dup_list: 
        if elem not in yooneeks: 
            yooneeks.append(elem) 
    return yooneeks

उदाहरण :

my_list = ['this','is','a','list','with','dupicates','in', 'the', 'list']

उपयोग:

rem_dupes(my_list)

['यह', 'है', 'ए', 'सूची', 'के साथ', 'दुविधा', 'में', 'द]


5

ऐसा करने के लिए अलग-अलग तरीकों का सुझाव देने वाले कई अन्य उत्तर हैं, लेकिन वे सभी बैच संचालन हैं, और उनमें से कुछ मूल आदेश को फेंक देते हैं। जो आपके लिए आवश्यक है, उसके आधार पर यह ठीक हो सकता है, लेकिन यदि आप प्रत्येक मान के पहले उदाहरण के क्रम में मूल्यों पर पुनरावृति करना चाहते हैं, और आप डुप्लिकेट को ऑन-द-फ्लाई बनाम एक ही बार में निकालना चाहते हैं, तो आप उपयोग कर सकते हैं यह जनरेटर:

def uniqify(iterable):
    seen = set()
    for item in iterable:
        if item not in seen:
            seen.add(item)
            yield item

यह एक जनरेटर / पुनरावृत्ति देता है, इसलिए आप इसे कहीं भी उपयोग कर सकते हैं कि आप एक पुनरावृत्ति का उपयोग कर सकते हैं।

for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):
    print(unique_item, end=' ')

print()

आउटपुट:

1 2 3 4 5 6 7 8

यदि आप एक चाहते हैं list, तो आप यह कर सकते हैं:

unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))

print(unique_list)

आउटपुट:

[1, 2, 3, 4, 5, 6, 7, 8]

seen = set(iterable); for item in seen: yield itemलगभग निश्चित रूप से तेज है। (मैंने इस विशिष्ट मामले की कोशिश नहीं की है, लेकिन यह मेरा अनुमान होगा।)
dylnmc

2
@dylnmc, यह एक बैच ऑपरेशन है, और यह ऑर्डर को भी खो देता है। मेरा उत्तर विशेष रूप से उड़ान भरने और पहली घटना के क्रम में होने का इरादा था। :)
सिपाही


5

आप setडुप्लिकेट को निकालने के लिए उपयोग कर सकते हैं :

mylist = list(set(mylist))

लेकिन ध्यान दें परिणाम अनियंत्रित होंगे। अगर यह एक मुद्दा है:

mylist.sort()

1
आप अभी कर सकते हैं: mylist = सॉर्ट किया गया (सूची (सेट (
mylist

5

एक और बेहतर तरीका हो सकता है,

import pandas as pd

myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanList = pd.Series(myList).drop_duplicates().tolist()
print(cleanList)

#> [1, 2, 3, 5, 6, 7, 8]

और आदेश संरक्षित रहता है।


हालांकि यह अच्छी तरह से काम कर सकता है, इस उद्देश्य के लिए पांडा जैसे भारी पुस्तकालय का उपयोग करना एक ओवरकिल की तरह लगता है।
ग्लुटेक्सो

4

यह आदेश बहुत अधिक परेशानी के बिना आदेश के बारे में परवाह करता है (ऑर्डरडिक और अन्य)। शायद सबसे पाइथोनिक तरीका नहीं है, और न ही सबसे छोटा तरीका है, लेकिन यह चाल है:

def remove_duplicates(list):
    ''' Removes duplicate items from a list '''
    singles_list = []
    for element in list:
        if element not in singles_list:
            singles_list.append(element)
    return singles_list

1. आपको कभी भी निर्मित नामों को छाया नहीं देना चाहिए (कम से कम, जितना महत्वपूर्ण हो list); 2. आपका तरीका बेहद खराब है: यह तत्वों की संख्या में द्विघात है list
एली कोरविगो

1. सही, लेकिन यह एक उदाहरण था; 2. सही है, और यही कारण है कि मैंने इसे पेश किया। यहां पोस्ट किए गए सभी समाधानों में पेशेवरों और विपक्ष हैं। कुछ त्याग सादगी या आदेश, मेरा बलिदान स्केलेबिलिटी।
cgf

यह एक "शलेमिल द पेंटर" एल्गोरिथम है ...
Z4-tier

4

नीचे दी गई सूची में डुप्लिकेट को हटाने के लिए सरल कोड है

def remove_duplicates(x):
    a = []
    for i in x:
        if i not in a:
            a.append(i)
    return a

print remove_duplicates([1,2,2,3,3,4])

यह लौटा [1,2,3,4]


2
यदि आप आदेश की परवाह नहीं करते हैं, तो इसमें काफी समय लगता है। list(set(..))(1 मिलियन से अधिक पास) इस समाधान को लगभग 10 सेकंड तक हरा देंगे - जबकि यह दृष्टिकोण लगभग 12 सेकंड list(set(..))लेता है , केवल लगभग 2 सेकंड लगते हैं!
dylnmc

@dylnmc यह भी काफी पुराने उत्तर
एली कोरविगो

4

यहाँ उत्तर में सूचीबद्ध सबसे तेज़ pythonic समाधान है।

शॉर्ट-सर्किट मूल्यांकन के कार्यान्वयन विवरण का उपयोग करने से सूची समझ का उपयोग करने की अनुमति मिलती है, जो कि काफी तेज है। visited.add(item)हमेशा Noneएक परिणाम के रूप में लौटता है , जिसका मूल्यांकन किया जाता है False, इसलिए दाईं ओरor हमेशा ऐसी अभिव्यक्ति का परिणाम होगा।

समय अपने आप

def deduplicate(sequence):
    visited = set()
    adder = visited.add  # get rid of qualification overhead
    out = [adder(item) or item for item in sequence if item not in visited]
    return out


4

दुर्भाग्य से। यहां अधिकांश उत्तर या तो आदेश को संरक्षित नहीं करते हैं या बहुत लंबे हैं। यहाँ एक सरल, आदेश संरक्षण जवाब है।

s = [1,2,3,4,5,2,5,6,7,1,3,9,3,5]
x=[]

[x.append(i) for i in s if i not in x]
print(x)

यह आपको हटाए गए डुप्लिकेट के साथ x देगा, लेकिन ऑर्डर को संरक्षित करेगा।


3

पायथन 3 में बहुत सरल तरीका:

>>> n = [1, 2, 3, 4, 1, 1]
>>> n
[1, 2, 3, 4, 1, 1]
>>> m = sorted(list(set(n)))
>>> m
[1, 2, 3, 4]

2
sorted(list(...))निरर्थक है ( sortedपहले से ही अपने तर्क को एक नए रूप में परिवर्तित करता है list, इसे सॉर्ट करता है, फिर नया लौटाता है list, इसलिए दोनों साधनों का उपयोग एक अनावश्यक अस्थायी बनाता है list)। केवल तभी उपयोग करें listजब परिणाम को क्रमबद्ध करने की आवश्यकता न हो, केवल तभी उपयोग करें sortedजब परिणाम को हल करने की आवश्यकता हो।
शैडो रेंजर

3

पायथन का जादू निर्मित प्रकार

अजगर में, इस तरह के जटिल मामलों को संसाधित करना बहुत आसान है और केवल अजगर के अंतर्निहित प्रकार से।

मैं तुम्हें कैसे दिखाऊं!

विधि 1: सामान्य मामला

सूची में डुप्लिकेट तत्व को हटाने का तरीका ( 1 लाइन कोड ) और फिर भी क्रमबद्ध क्रमबद्ध रखना

line = [1, 2, 3, 1, 2, 5, 6, 7, 8]
new_line = sorted(set(line), key=line.index) # remove duplicated element
print(new_line)

आपको इसका परिणाम मिलेगा

[1, 2, 3, 5, 6, 7, 8]

विधि 2: विशेष मामला

TypeError: unhashable type: 'list'

विशेष मामले को अनहैसेबल ( 3 लाइन कोड ) संसाधित करने के लिए

line=[['16.4966155686595', '-27.59776154691', '52.3786295521147']
,['16.4966155686595', '-27.59776154691', '52.3786295521147']
,['17.6508629295574', '-27.143305738671', '47.534955022564']
,['17.6508629295574', '-27.143305738671', '47.534955022564']
,['18.8051102904552', '-26.688849930432', '42.6912804930134']
,['18.8051102904552', '-26.688849930432', '42.6912804930134']
,['19.5504702331098', '-26.205884452727', '37.7709192714727']
,['19.5504702331098', '-26.205884452727', '37.7709192714727']
,['20.2929416861422', '-25.722717575124', '32.8500163147157']
,['20.2929416861422', '-25.722717575124', '32.8500163147157']]

tuple_line = [tuple(pt) for pt in line] # convert list of list into list of tuple
tuple_new_line = sorted(set(tuple_line),key=tuple_line.index) # remove duplicated element
new_line = [list(t) for t in tuple_new_line] # convert list of tuple into list of list

print (new_line)

आपको परिणाम मिलेगा:

[
  ['16.4966155686595', '-27.59776154691', '52.3786295521147'], 
  ['17.6508629295574', '-27.143305738671', '47.534955022564'], 
  ['18.8051102904552', '-26.688849930432', '42.6912804930134'], 
  ['19.5504702331098', '-26.205884452727', '37.7709192714727'], 
  ['20.2929416861422', '-25.722717575124', '32.8500163147157']
]

चूँकि tuple hashes योग्य है और आप सूची और tuple के बीच आसानी से डेटा परिवर्तित कर सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.