2012-03-05 5 views
6

में एकाधिक सूचियों में सामान्य सूची तत्वों को निकालने का सबसे आसान तरीका मेरे पास संख्याओं की सूची है। मैं यह सुनिश्चित करना चाहता हूं कि प्रत्येक सूची में उस विशेष सूची में अद्वितीय तत्व हों। अर्थात। बाकी में से किसी भी "साझा" डुप्लिकेट नहीं हैं।
यह दो सूचियों के साथ करना वास्तव में आसान है, लेकिन एन सूचियों के साथ थोड़ा सा चालक है।पायथन

e.g. 
mylist = [ 
[1, 2, 3, 4], 
[2, 5, 6, 7], 
[4, 2, 8, 9] 
] 

हो जाता है:

mylist = [ 
[1, 3], 
[5, 6, 7], 
[8, 9] 
] 
+4

तीन सूची में से किसी एक में 2 क्यों नहीं है, जबकि 4 अभी भी पहली सूची में मौजूद है? –

+1

क्या आपको परवाह है कि आदेश संरक्षित है या नहीं? – wim

+0

"देखी गई" सूची बनाने के लिए एक बैग ('default_dict') का उपयोग करें। 'माईलिस्ट' की प्रत्येक सूची को बदलें (मैं इसे 'sublist' कहूंगा) एक जनरेटर के साथ जो मिलान करने वाला' देखा' ढूंढता है: यदि पाया गया है, तो इसे अंतिम 'sublist' में शामिल न करें। यदि नहीं मिला, तो इसे बैग में जोड़ें। – Droogans

उत्तर

5
from collections import Counter 
from itertools import chain 

mylist = [ 
    [1,2,3,4], 
    [2,5,6,7,7], 
    [4,2,8,9] 
] 

counts = Counter(chain(*map(set,mylist))) 

[[i for i in sublist if counts[i]==1] for sublist in mylist] 
#[[1, 3], [5, 6, 7, 7], [8, 9]] 
+0

यह वास्तव में अच्छा है, लेकिन मैं काउंटर और चेन आयात करने के लिए मुझे पसंद नहीं करना चाहूंगा क्योंकि इससे चलने वाले समय (?) को थोड़ा कम हो सकता है। – LittleBobbyTables

+0

!!! मैं अपने जवाब में एक सुंदर तरीके से 'श्रृंखला (* मेरी सूची)' करने का एक तरीका ढूंढ रहा था। बहुत अच्छा। ओह, और मुझे अपने उत्तर में '.get()' की भी आवश्यकता नहीं है क्योंकि निश्चित रूप से इसे हमेशा परिभाषित किया जाएगा। मैं अपना जवाब हटा रहा हूं क्योंकि आपका लगभग बिल्कुल वही है लेकिन कड़ाई से बेहतर है। – ninjagecko

+2

@ मैथ्यूआरएनवाईसी: आपको इस तरह के मूल सुझावों का उपयोग करने से डरना नहीं चाहिए। इसके अतिरिक्त मुझे कोई कारण नहीं दिख सकता कि 'चेन' और 'काउंटर' कन्स्ट्रक्टर दोनों 'ओ (एन) 'नहीं होंगे। – ninjagecko

2

यह रेखीय समय, 2 गुजरता में यह होता है। मुझे लगता है कि आप सूची में डुप्लिकेट को संरक्षित करना चाहते हैं; यदि नहीं, तो इस थोड़ा सरल किया जा सकता:

>>> import collections, itertools 
>>> counts = collections.defaultdict(int) 
>>> for i in itertools.chain.from_iterable(set(l) for l in mylist): 
...  counts[i] += 1 
... 
>>> for l in mylist: 
...  l[:] = (i for i in l if counts[i] == 1) 
... 
>>> mylist 
[[1, 3], [5, 6, 7], [8, 9]] 
+0

यह एक बार देखा आइटमों में छोड़ देता है, यकीन नहीं है कि ओपी चाहता है कि .. – wim

+0

@wim, धन्यवाद, तय है। – senderle

1

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

>>> mylist = [ 
... [1, 2, 3, 4], 
... [2, 5, 6, 7], 
... [4, 2, 8, 9] 
... ] 
>>> mynewlist = [list(set(thislist) - set(element for sublist in mylist for element in sublist if sublist is not thislist)) for thislist in mylist] 
>>> mynewlist 
[[1, 3], [5, 6, 7], [8, 9]] 

नोट: यह बहुत ही कुशल है क्योंकि डुप्लिकेट प्रत्येक पंक्ति के लिए की पुनर्गणना की जाती नहीं है। चाहे यह एक समस्या है या नहीं, आपके डेटा आकार पर निर्भर करता है।

+1

यह एक जानवर है!:) – LittleBobbyTables

+0

हालांकि एक महंगा ऑपरेशन की तरह लग रहा है। यदि आपके पास 'एम' तत्वों के साथ 'n' सूचियां हैं, तो आपके पास' ओ (एन * एन -1 * एम) 'जैसी कुछ है (जो केवल प्रत्येक उपन्यास के प्रत्येक तत्व पर पुनरावृत्ति के लिए है)। या मैं गलत हूँ? –

+0

दुर्भाग्यवश मुझे -1 होना है: यह प्रत्येक सूची के लिए सभी डुप्लिकेट का पुनर्मूल्यांकन करता है, जिसके परिणामस्वरूप लगभग ओ ओ (एन^(3/2)) 'कार्य होता है जो उपन्यासों की संख्या 'sqrt (N)' जैसा होता है। न ही यह एक सूची के क्रम को संरक्षित करता है (यद्यपि सूचियों को क्रमबद्ध किया गया था, फिर भी आप एक बहुगुणित 'ओ (लॉग (sublistN))' कारक अतिरिक्त) की लागत पर उन्हें फिर से क्रमबद्ध कर सकते हैं। मैं व्यक्तिगत रूप से 'काउंटर' समाधान के साथ जाऊंगा जो मुझे विश्वास है कि 'ओ (एन) 'है। – ninjagecko

0

सेट() सही दृष्टिकोण है। हालांकि आपको सूची समझ का उपयोग करने की आवश्यकता नहीं है।

अतिरिक्त आयात के बिना:

mylist = [ 
[1, 2, 3, 4], 
[2, 5, 6, 7], 
[4, 2, 8, 9] 
] 
>>> result_list = [] 
>>> for test_list in mylist: 
...  result_set = set(test_list) 
...  for compare_list in mylist: 
...   if test_list != compare_list: 
...    result_set = result_set - set(compare_list) 
...  result_list.append(result_set) 
... 
>>> result_list 
[set([1, 3]), set([5, 6, 7]), set([8, 9])] 
0

यह मेरा समाधान है, Counter का उपयोग कर सभी आम संख्याओं के एक समूह का निर्माण करने, और फिर यह सिर्फ एक सेट अंतर करता है:

from collections import Counter 

def disjoin(lsts): 
    c = Counter(num for lst in lsts for num in lst) 
    common = set(x for x,v in c.items() if v > 1) 
    result = [] 
    for lst in lsts: 
     result.append(set(lst) - common) 
    return result 

उदाहरण:

>>> remove_common(mylist) 
[set([1, 3]), set([5, 6, 7]), set([8, 9])]