अजगर को एक सूची में ऐसे तत्व मिलते हैं जो दूसरे में नहीं हैं [डुप्लिकेट]


136

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

main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"] 

मैं list_1 के माध्यम से लूप करना चाहता हूं और list_2 से सभी तत्वों को main_list में सूचीबद्ध करना चाहता हूं जो सूची_1 में नहीं पाए जाते हैं।

परिणाम होना चाहिए:

main_list=["f", "m"]

मैं इसे अजगर के साथ कैसे कर सकता हूं?


2
क्या आप उन तत्वों की तलाश कर रहे हैं list_2जो कहीं दिखाई देते हैं list_1या ऐसे तत्व list_2जो उसी सूचकांक में मौजूद नहीं हैं list_1?
पैट्रिक हॉग

जवाबों:


98

टीएल; डीआर:
समाधान (1)

import numpy as np
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`

समाधान (2) आप क्रमबद्ध सूची चाहते हैं

def setdiff_sorted(array1,array2,assume_unique=False):
    ans = np.setdiff1d(array1,array2,assume_unique).tolist()
    if assume_unique:
        return sorted(ans)
    return ans
main_list = setdiff_sorted(list_2,list_1)




EXPLANATIONS:
(1) आप NumPy's , setdiff1d( , = ) का उपयोग कर सकते हैं ।array1array2assume_uniqueFalse

assume_uniqueउपयोगकर्ता पूछता है कि क्या सरणियाँ पहले से ही हैं।
यदि False, तो पहले अद्वितीय तत्व निर्धारित किए जाते हैं।
यदि True, फ़ंक्शन मान लेगा कि तत्व पहले से ही अद्वितीय हैं और फ़ंक्शन अद्वितीय तत्वों को निर्धारित करना छोड़ देगा।

यह उन अद्वितीय मूल्यों को जन्म देता है array1जो इसमें नहीं हैं array2assume_uniqueहै Falseडिफ़ॉल्ट रूप से।

यदि आप अनूठे तत्वों ( चिन्नी84 की प्रतिक्रिया के आधार पर ) से चिंतित हैं , तो बस उपयोग करें (जहां assume_unique=False=> डिफ़ॉल्ट मान):

import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"] 
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`


(२) उन लोगों के लिए जो उत्तर क्रमबद्ध करना चाहते हैं, मैंने एक कस्टम फंक्शन बनाया है:

import numpy as np
def setdiff_sorted(array1,array2,assume_unique=False):
    ans = np.setdiff1d(array1,array2,assume_unique).tolist()
    if assume_unique:
        return sorted(ans)
    return ans

उत्तर पाने के लिए, दौड़ें:

main_list = setdiff_sorted(list_2,list_1)

साइड नोट:
(ए) समाधान 2 (कस्टम फ़ंक्शन setdiff_sorted) एक सूची देता है ( समाधान 1 में एक सरणी की तुलना में)।

(बी) यदि आप सुनिश्चित नहीं हैं कि तत्व अद्वितीय हैं, तो बस setdiff1dसमाधान ए और बी दोनों में NumPy's की डिफ़ॉल्ट सेटिंग का उपयोग करें । एक जटिलता का एक उदाहरण क्या हो सकता है? नोट देखें (c)

(c) यदि दोनों सूचियाँ अद्वितीय नहीं हैं तो चीजें अलग होंगी ।
कहना list_2अद्वितीय नहीं है list2 = ["a", "f", "c", "m", "m"]:। इस प्रकार रखें list1: पैदावार list_1 = ["a", "b", "c", "d", "e"]
के डिफ़ॉल्ट मूल्य को निर्धारित करना (दोनों समाधानों में)। यदि आप सेट करते हैं , तो दोनों समाधान देते हैं । क्यों? ऐसा इसलिए है क्योंकि उपयोगकर्ता ने माना है कि तत्व अद्वितीय हैं)। इसलिए, यह KEEP के लिए बेहतर हैassume_unique["f", "m"]assume_unique=True["f", "m", "m"]assume_uniqueइसके डिफ़ॉल्ट मूल्य के लिए। ध्यान दें कि दोनों उत्तर हल किए गए हैं।


यदि आपकी सूचियां पहले से ही ऑर्डर की गई हैं, तो यह एक आदेशित सूची भी लौटाएगा। सेट में परिवर्तित करने और फिर अंतर (नीचे दिखाए गए समाधान) प्राप्त करने का मूल समाधान एक अनियंत्रित सूची देता है जो आपके परिणामों की दृष्टि से जांच करना कठिन बना सकता है।
डबल्डडाउन

1
हाय, @Doubledown! आपकी चिंता को संपादित पोस्ट में संबोधित किया गया है। उम्मीद है की यह मदद करेगा!
jcoderepo

183

आप सेट का उपयोग कर सकते हैं:

main_list = list(set(list_2) - set(list_1))

आउटपुट:

>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']

@JonClements की टिप्पणी के अनुसार, यहाँ एक ख़ास संस्करण है:

>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']

2
यह अच्छा है अगर हम केवल uniqueतत्वों की परवाह करते हैं लेकिन क्या होगा यदि हमारे पास m'sउदाहरण के लिए कई हैं तो यह इसे नहीं उठाएगा।
चिन्नी 13४

यह सच है। मुझे लगा कि पोस्टर अद्वितीय तत्वों की तलाश कर रहा है। मुझे लगता है कि यह उस पर निर्भर करता है कि वह "विशिष्ट" से क्या मतलब है।
nrlakin

वास्तव में पीएस मैंने आपके उत्तर को अस्वीकार नहीं किया, विशेष रूप से अस्पष्ट मूल प्रश्न के लिए।
चिन्नी 13४

13
आप लिख सकते के रूप में list(set(list_2).difference(list_1))जो स्पष्ट बचा जाता है setरूपांतरण ...
जॉन क्लेमेंट्स

कोई चिंता नहीं! प्रारूपण सहायता के लिए धन्यवाद @leaf।
nrlakin

61

यह सुनिश्चित नहीं है कि जब आपके पास देशी तरीके उपलब्ध हैं तो उपरोक्त स्पष्टीकरण इतने जटिल क्यों हैं:

main_list = list(set(list_2)-set(list_1))

6
संरक्षित करने का कारण हो सकता है
कीथ

57

इस तरह एक सूची समझ का उपयोग करें:

main_list = [item for item in list_2 if item not in list_1]

आउटपुट:

>>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"] 
>>> 
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']

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

जैसा कि नीचे दी गई टिप्पणियों में उल्लेख किया गया है, बड़ी सूचियों के साथ, ऊपर आदर्श समाधान नहीं है। जब ऐसी बात है, एक बेहतर विकल्प परिवर्तित किया जाएगा list_1एक करने के लिए setपहले:

set_1 = set(list_1)  # this reduces the lookup time from O(n) to O(1)
main_list = [item for item in list_2 if item not in set_1]

3
नोट: बड़े के लिए list_1, आप set/ frozenset, जैसे set_1 = frozenset(list_1), फिर main_list = [item for item in list_2 if item not in set_1], O(n)प्रति आइटम से चेक समय को कम करना (लगभग) के लिए पूर्वसर्ग करना चाहते हैं O(1)
शैडो रेंजर

@ शिष्टाचार कृपया ध्यान रखें अगर आप समाधान के रूप में प्रयास करें तो एटैननी पोस्ट करें। मैंने ettanany के समाधान की कोशिश की है और यह वास्तव में एक बड़ी सूची के लिए सुपर स्लो है। क्या आप छायाकार के सुझाव को शामिल करने के लिए उत्तर को अपडेट कर सकते हैं?
डबलडाउन

क्या यह स्ट्रिंग के बजाय सूचकांक प्राप्त करना संभव होगा?
जारेबियर

@JareBear आप इसके लिए उपयोग कर सकते हैं enumerate():[index for (index, item) in enumerate(list_2) if item not in list_1]
ettanany

@ एतानानी का बहुत-बहुत धन्यवाद !! मैं उस asap को लागू करूँगा, मैंने किया था। लेकिन आपका कोड इतना साफ दिखता है।
JareBear

5

आप एक लाइनर समाधान (आयात अनदेखी) है कि केवल आवश्यकता चाहते हैं O(max(n, m))लंबाई के आदानों के लिए काम करते nहैं और m, नहीं O(n * m)काम करते हैं, आप के साथ ऐसा कर सकते हैं मॉड्यूल :itertools

from itertools import filterfalse

main_list = list(filterfalse(set(list_1).__contains__, list_2))

यह निर्माण पर एक कॉलबैक फ़ंक्शन लेने वाले कार्यात्मक कार्यों का लाभ उठाता है, जिससे इसे एक बार कॉलबैक बनाने की अनुमति मिलती है और इसे हर तत्व के लिए पुन: उपयोग करने की आवश्यकता होती है इसे कहीं स्टोर करने की आवश्यकता नहीं है (क्योंकि filterfalseयह आंतरिक रूप से संग्रहीत करता है); सूची की समझ और जनरेटर के भाव यह कर सकते हैं, लेकिन यह बदसूरत है।

कि एक ही लाइन में एक ही परिणाम के रूप में हो जाता है:

main_list = [x for x in list_2 if x not in list_1]

की गति के साथ:

set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]

बेशक, यदि तुलना का उद्देश्य स्थितिगत होना है, तो:

list_1 = [1, 2, 3]
list_2 = [2, 3, 4]

उत्पादन करना चाहिए:

main_list = [2, 3, 4]

(क्योंकि वैल्यू में list_2एक ही इंडेक्स पर एक मैच होता है list_1), आपको निश्चित रूप से पैट्रिक के उत्तर के साथ जाना चाहिए , जिसमें कोई अस्थायी listएस या setएस नहीं है (यहां तक ​​कि setमोटे तौर पर एस होने के साथ O(1), उनके पास साधारण समानता की जांच की तुलना में एक उच्च "स्थिर" कारक है। ) और O(min(n, m))किसी भी अन्य उत्तर की तुलना में कम काम शामिल है , और यदि आपकी समस्या स्थिति के प्रति संवेदनशील है, तो एकमात्र सही समाधान है जब मिलान करने वाले तत्व बेमेल स्थानों पर दिखाई देते हैं।

Do: एक-लाइनर के रूप में एक सूची समझ के साथ एक ही काम करने का तरीका "सबसे बाहरी" लूप में उदासीन और मूल्य को कैश करने के लिए नेस्टेड लूपिंग का दुरुपयोग करना होगा, जैसे:

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]

जो कि पायथन 3 पर एक मामूली प्रदर्शन लाभ भी देता है (क्योंकि अब set_1स्थानीय रूप से कॉम्प्रिहेंशन कोड में स्कोप किया जाता है, बजाय प्रत्येक चेक के लिए नेस्टेड स्कोप से देखा जाता है; पायथन 2 पर जो मायने नहीं रखता, क्योंकि पायथन 2 क्लोजर का उपयोग नहीं करता है; सूची की समझ; वे उसी दायरे में काम करते हैं जिसका वे उपयोग कर रहे हैं)।


4
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]

for i in list_2:
    if i not in list_1:
        main_list.append(i)

print(main_list)

उत्पादन:

['f', 'm']

जैसा बराबर सूची समझ आधारित समाधान , इस धीमी गति से हो सकता है अगर list_1बड़ी है, और list_2गैर तुच्छ आकार की है, क्योंकि यह शामिल है len(list_2) O(n)के स्कैन list_1, जिससे यह O(n * m)(जहां nऔर mके समान नहीं हैं list_2और list_1क्रमशः)। यदि आप list_1एक set/ frozensetअप फ्रंट में कनवर्ट करते हैं , तो इसमें शामिल चेक किए जा सकते हैं O(1), जो कुल O(n)लंबाई का काम कर रहा है list_2(तकनीकी रूप O(max(n, m))से, जब से आप O(m)काम करते हैं set)।
शैडो रेंजर

1

मैं zipतत्वों द्वारा तत्व की तुलना करने के लिए सूचियों को एक साथ रखूंगा।

main_list = [b for a, b in zip(list1, list2) if a!= b]

अगर ओपी तत्व द्वारा तत्व की तुलना करना चाहता है (यह स्पष्ट नहीं है, उदाहरण किसी भी तरह से जा सकता है), तो यह अन्य उत्तरों की तुलना में बहुत अधिक कुशल है, क्योंकि यह listएक ही नए listनिर्माण के साथ दोनों पर एक ही सस्ता पास है , कोई अतिरिक्त अस्थायी नहीं , कोई महंगी रोकथाम की जाँच, आदि
ShadowRanger

1
@ शादो रेंजर केवल तत्व-वार अंतर के लिए काम करेंगे जो एक महत्वपूर्ण बिंदु है
ford प्रीफेक्ट

@ ऑर्डपोरफेक्ट: यूप। मेरा अपना उत्तर स्थिति-स्वतंत्र अंतरों को कवर करता है।
शैडो रेंजर

1

मैंने दो तरीकों का इस्तेमाल किया और मुझे एक तरीका दूसरे पर उपयोगी लगा। यहाँ मेरा जवाब है:

मेरा इनपुट डेटा:

crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']

Method1: np.setdiff1dमुझे अन्य पर यह दृष्टिकोण पसंद है क्योंकि यह स्थिति को संरक्षित करता है

test= list(np.setdiff1d(testmod_mpp,crkmod_mpp))
print(test)
['M15', 'M16', 'M22', 'M23', 'M20', 'M14', 'M17', 'M21']

Method2: हालाँकि यह Method1 में एक ही उत्तर देता है, लेकिन आदेश को परेशान करता है

test = list(set(testmod_mpp).difference(set(crkmod_mpp)))
print(test)
['POA23', 'POA15', 'POA17', 'POA16', 'POA22', 'POA18', 'POA24', 'POA21']

Method1 np.setdiff1dमेरी आवश्यकताओं को पूरी तरह से पूरा करता है। जानकारी के लिए यह उत्तर।


0

यदि घटनाओं की संख्या को ध्यान में रखा जाना चाहिए, तो आपको संभवतः कुछ का उपयोग करने की आवश्यकता है collections.Counter:

list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"] 
from collections import Counter
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]

>>> final
['f', 'm']

जैसा कि वादा किया गया है कि यह "अंतर" के रूप में होने वाली घटनाओं की संख्या को भी संभाल सकता है:

list_1=["a", "b", "c", "d", "e", 'a']
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]

>>> final
['a', 'f', 'm']

-1

Ser1 से ser2 में मौजूद वस्तुओं को हटा दें।

इनपुट

ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])

उपाय

ser1 [~ ser1.isin (ser2)]


ढेर अतिप्रवाह में आपका स्वागत है। इस प्रश्न के आठ अन्य उत्तर हैं, जिनमें से एक को मूल पोस्टर द्वारा स्वीकार किया गया है। कृपया बताएं कि आपका उत्तर पहले से ही प्रस्तुत किए गए कार्यों में कैसे सुधार करता है।
chb
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.