उन सभी तत्वों को हटा दें जो एक सूची में दूसरे से आते हैं


365

मान लीजिए कि मेरे पास दो सूचियाँ हैं, l1और l2। मैं प्रदर्शन करना चाहता हूं l1 - l2, जो l1नहीं के सभी तत्वों को लौटाता है l2

मैं ऐसा करने के लिए एक भोले पाश दृष्टिकोण के बारे में सोच सकता हूं, लेकिन यह वास्तव में अक्षम होने जा रहा है। यह करने का एक पायथोनिक और कुशल तरीका क्या है?

एक उदाहरण के रूप में, अगर मेरे पास है l1 = [1,2,6,8] and l2 = [2,3,5,8], तो l1 - l2वापस लौटना चाहिए[1,6]


12
बस एक टिप: PEP8 कहता है कि लोअरकेस "L" का इस्तेमाल नहीं किया जाना चाहिए क्योंकि यह बहुत ज्यादा दिखता है जैसे 1.
स्पेलचेकर

2
मैं सहमत हूँ। मैंने इस पूरे प्रश्न और उत्तर को पढ़कर आश्चर्य किया कि लोग ग्यारह और बारह का उपयोग क्यों करते रहे। जब मैंने @spelchekr की टिप्पणी पढ़ी, तभी समझ में आया।
डकैती


@JimG। डेटाफ्रेम और सूची एक ही बात नहीं है।
गतिविधि

जवाबों:


491

पायथन में लिस्ट कॉम्प्रिहेंशन नामक एक भाषा सुविधा है जो इस तरह की चीज़ को बेहद आसान बनाने के लिए पूरी तरह से अनुकूल है। निम्नलिखित कथन ठीक वही करता है जो आप चाहते हैं और परिणाम को इसमें संग्रहीत करता है l3:

l3 = [x for x in l1 if x not in l2]

l3शामिल होंगे [1, 6]


8
बहुत अजगर; मुझें यह पसंद है! यह कितना कुशल है?
प्रशंसक

2
मेरा मानना ​​है कि यह काफी कुशल है, और यह बेहद पठनीय और स्पष्ट होने का लाभ है कि आप क्या हासिल करना चाहते हैं। मुझे एक ब्लॉग पोस्ट मिली जो आपको दक्षता से संबंधित दिलचस्प लग सकती है: blog.cdleary.com/2010/04/efficiency-of-list-comprehensions
डोनट

6
@fandom: लिस्ट कॉम्प्रिहेंशन अपने आप में काफी कुशल है (हालाँकि जेनरेटर कॉम्प्रिहेंशन मेमोरी में एलिमेंट्स को डुप्लिकेट न करके अधिक कुशल हो सकता है), लेकिन inऑपरेटर किसी लिस्ट में उतना कुशल नहीं है। inसूची में O (n) है, जबकि inएक सेट पर O (1) है। हालाँकि, जब तक आपको हजारों तत्व या अधिक नहीं मिलते, तब तक आप अंतर को नोटिस नहीं कर सकते।
डैनियल प्राइडेन

1
l3 = [x for x in l1 if x not in set(l2)]? मुझे यकीन है कि अगर set(l2)एक से अधिक बार बुलाया जाएगा।
6

5
आप भी बस सेट कर सकते हैं l2s = set(l2)और फिर कह सकते हैं l3 = [x for x in l1 if x not in l2s]। थोड़ा आसान है।
स्पेलचेकर

149

एक तरीका सेट का उपयोग करना है:

>>> set([1,2,6,8]) - set([2,3,5,8])
set([1, 6])

58
यह डुप्लिकेट को भी हटा देगा l1, जो एक अवांछित साइड इफेक्ट हो सकता है।
नोवा

37
..और तत्व क्रम खो (यदि आदेश महत्वपूर्ण है)।
Danosaure

3
मैं केवल यह जोड़ना चाहता हूं कि मैंने यह स्वीकार किए गए उत्तर के अनुसार समय दिया है और यह लगभग 3: के कारक द्वारा अधिक प्रदर्शनकारी था timeit.timeit('a = [1,2,3,4]; b = [1,3]; c = [i for i in a if a not in b]', number=100000) -> 0.12061533199999985 timeit.timeit('a = {1,2,3,4}; b = {1,3}; c = a - b', number=100000) -> 0.04106225999998969। इसलिए यदि प्रदर्शन एक महत्वपूर्ण कारक है, तो यह उत्तर अधिक उपयुक्त हो सकता है (और यदि आप डुप्लिकेट या ऑर्डर की परवाह नहीं करते हैं)
wfgeo

37

एक विकल्प के रूप में, आप वांछित परिणाम प्राप्त करने के लिए लैम्ब्डा अभिव्यक्ति के साथ भी उपयोगfilter कर सकते हैं । उदाहरण के लिए:

>>> l1 = [1,2,6,8]
>>> l2 = set([2,3,5,8])

#     v  `filter` returns the a iterator object. Here I'm type-casting 
#     v  it to `list` in order to display the resultant value
>>> list(filter(lambda x: x not in l2, l1))
[1, 6]

प्रदर्शन की तुलना

यहां मैं यहां वर्णित सभी उत्तरों के प्रदर्शन की तुलना कर रहा हूं। जैसी कि उम्मीद थी, अर्कुक का set आधारित ऑपरेशन सबसे तेज़ है।

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


32

डोनट के उत्तर और यहां के अन्य उत्तरों पर विस्तार करते हुए, आप एक सूची समझ के बजाय एक जनरेटर समझ का उपयोग करके और एक setडेटा संरचना का उपयोग करके भी बेहतर परिणाम प्राप्त कर सकते हैं (चूंकि inऑपरेटर एक सूची में O (n) है, लेकिन O (1) एक सेट पर)।

तो यहाँ एक फ़ंक्शन है जो आपके लिए काम करेगा:

def filter_list(full_list, excludes):
    s = set(excludes)
    return (x for x in full_list if x not in s)

परिणाम एक पुनरावृत्ति होगा जो फ़िल्टर की गई सूची को आलसी रूप से प्राप्त करेगा। यदि आपको एक वास्तविक सूची ऑब्जेक्ट की आवश्यकता है (जैसे यदि आपको len()परिणाम पर करने की आवश्यकता है ), तो आप आसानी से इस तरह की सूची बना सकते हैं:

filtered_list = list(filter_list(full_list, excludes))

29

पायथन सेट प्रकार का उपयोग करें। यह सबसे पाइथोनिक होगा। :)

इसके अलावा, चूंकि यह मूल है, इसलिए यह सबसे अनुकूलित तरीका भी होना चाहिए।

देख:

http://docs.python.org/library/stdtypes.html#set

http://docs.python.org/library/sets.htm (पुराने अजगर के लिए)

# Using Python 2.7 set literal format.
# Otherwise, use: l1 = set([1,2,6,8])
#
l1 = {1,2,6,8}
l2 = {2,3,5,8}
l3 = l1 - l2

5
सेट का उपयोग करते समय यह ध्यान दिया जाना चाहिए कि आउटपुट का आदेश दिया गया है, अर्थात {1,3,2} {1,2,3} और {"A", "C", "B"} बन जाता है {"A", "B", "C"} और आप ऐसा नहीं करना चाह सकते हैं।
पाब्लो

2
यदि सूची l1में बार-बार तत्व शामिल हैं तो यह विधि काम नहीं करेगी ।
jdhao

10

उपयोग सेट comprehensions {x के लिए x में l2} या सेट (L2) सेट प्राप्त करने के लिए, तो का उपयोग सूची comprehensions सूची प्राप्त करने के

l2set = set(l2)
l3 = [x for x in l1 if x not in l2set]

बेंचमार्क टेस्ट कोड:

import time

l1 = list(range(1000*10 * 3))
l2 = list(range(1000*10 * 2))

l2set = {x for x in l2}

tic = time.time()
l3 = [x for x in l1 if x not in l2set]
toc = time.time()
diffset = toc-tic
print(diffset)

tic = time.time()
l3 = [x for x in l1 if x not in l2]
toc = time.time()
difflist = toc-tic
print(difflist)

print("speedup %fx"%(difflist/diffset))

बेंचमार्क परीक्षा परिणाम:

0.0015058517456054688
3.968189239501953
speedup 2635.179227x    

1
l2set = set( l2 )इसके बजायl2set = { x for x in l2 }
cz

1
अच्छी आत्मा! लेकिन यह ध्यान में रखा जाना चाहिए, कि यह केवल हैशेबल ऑब्जेक्ट्स के साथ काम करता है।
इरिक स्वेन प्यूडिस्ट

7

वैकल्पिक समाधान:

reduce(lambda x,y : filter(lambda z: z!=y,x) ,[2,3,5,8],[1,2,6,8])

2
क्या इस पद्धति का उपयोग करने का कोई फायदा है? ऐसा लगता है कि यह बिना अधिक लाभ के पढ़ने के लिए अधिक जटिल और कठिन है।
skrrgwasme

यह जटिल लग सकता है। कम करना बहुत लचीला है और इसका उपयोग बहुत सारे उद्देश्यों के लिए किया जा सकता है। इसे तह के नाम से जाना जाता है। कम करना वास्तव में गुना है। मान लें कि आप इसमें और अधिक जटिल चीजें जोड़ना चाहते हैं तो यह इस फ़ंक्शन में संभव होगा लेकिन सूची की समझ जो चयनित सर्वश्रेष्ठ उत्तर है, आपको केवल उसी प्रकार का एक आउटपुट मिलेगा अर्थात सूची और संभवतः समान लंबाई जबकि सिलवटों के साथ आप कर सकते हैं आउटपुट प्रकार भी बदलें। en.wikipedia.org/wiki/Fold_%28higher-order_function%29 । यह समाधान n * m या उससे कम जटिलता है। हालांकि अन्य बेहतर हो सकते हैं या नहीं।
अक्षय हजारी

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