अगर एक सूची दूसरे की सबसेट है तो मैं कैसे सत्यापित कर सकता हूं?


184

मुझे यह सत्यापित करने की आवश्यकता है कि क्या कोई सूची किसी अन्य की सबसेट है - एक बूलियन रिटर्न है जो मुझे चाहिए।

एक चौराहे के बाद छोटी सूची पर समानता का परीक्षण करना ऐसा करने का सबसे तेज़ तरीका है? प्रदर्शन को अत्यंत महत्व दिया जाता है, जो की तुलना में आवश्यक डेटासेट की संख्या को दिया जाता है।

चर्चा के आधार पर और तथ्य जोड़ना:

  1. या तो कई परीक्षणों के लिए सूचियां समान होंगी? यह उनमें से एक के रूप में एक स्थिर लुकअप तालिका है।

  2. क्या यह एक सूची होने की आवश्यकता है? यह नहीं है - स्थिर लुकअप तालिका कुछ भी हो सकती है जो सबसे अच्छा प्रदर्शन करती है। डायनामिक एक ऐसा तानाशाह है जिससे हम एक स्थिर लुकअप करने के लिए कुंजियों को निकालते हैं।

परिदृश्य को देखते हुए इष्टतम समाधान क्या होगा?


आप गति का उल्लेख करते हैं, शायद आपके उपयोग के आधार पर, खतना उपयोगी होगा।
निनमोंकी

2
क्या सूची आइटम हैशेबल हैं?
विम

2
यदि आदेश महत्वपूर्ण है, तो यह एक अच्छी शुरुआत हो सकती है

क्या आपको उचित उपसमुच्चय की आवश्यकता है, या क्या वे समान हो सकते हैं?
törzsmókus

2
क्यों नहीं सेट (list_a) .issubset (सेट (list_b))?
सेफ़

जवाबों:


127

प्रदर्शन करने वाला कार्य पायथन इसके लिए प्रदान करता है set.issubset। यह कुछ प्रतिबंध है कि अगर यह आपके सवाल का जवाब है, हालांकि यह स्पष्ट नहीं है।

एक सूची में कई बार आइटम हो सकते हैं और एक विशिष्ट क्रम है। एक सेट नहीं होता है। इसके अतिरिक्त, सेट केवल हैशेबल वस्तुओं पर काम करते हैं।

क्या आप उपसमुच्चय या परवर्ती के बारे में पूछ रहे हैं (जिसका अर्थ है कि आप एक स्ट्रिंग खोज एल्गोरिदम चाहते हैं)? या तो कई परीक्षणों के लिए सूचियां समान होंगी? सूची में निहित डेटाटिप्स क्या हैं? और उस मामले के लिए, क्या यह एक सूची होने की आवश्यकता है?

आपकी अन्य पोस्ट ने एक तानाशाही को सूचीबद्ध किया और सूची ने प्रकार स्पष्ट किए और उनकी सेट-जैसी कार्यक्षमता के लिए शब्दकोश महत्वपूर्ण विचारों का उपयोग करने के लिए एक सिफारिश प्राप्त की। उस स्थिति में यह काम करने के लिए जाना जाता था क्योंकि शब्दकोश कुंजियाँ एक सेट की तरह व्यवहार करती हैं (इतना है कि इससे पहले कि हम पायथन में सेट करते हैं हम शब्दकोश का उपयोग करते हैं)। एक आश्चर्य है कि तीन घंटों में यह मुद्दा कम विशिष्ट कैसे हो गया।


मैं केवल एक सबसेट की बात कर रहा हूँ और issubset सिर्फ ठीक करता है - धन्यवाद। हालाँकि मैं यहाँ 2 प्रश्नों के बारे में उत्सुक हूँ। 1. क्या दोनों सूचियों में से कई परीक्षणों के लिए समान हैं? यह उनमें से एक के रूप में करता है एक स्थिर लुकअप तालिका 2. क्या यह एक सूची होने की आवश्यकता है? यह नहीं है - स्थिर लुकअप तालिका कुछ भी हो सकती है जो सबसे अच्छा प्रदर्शन करती है। डायनामिक एक ऐसा तानाशाह है जिससे हम एक स्थिर लुकअप करने के लिए कुंजियों को निकालते हैं। क्या यह तथ्य समाधान को बदल देगा?
IUnknown

बहुत ज्यादा नहीं। एक शब्दकोश की चाबियाँ सेट-जैसे हैं और पहले से ही एक हैश तालिका में व्यवस्थित हैं, और इसलिए स्थिर हिस्से के लिए सेट का उपयोग करने से अतिरिक्त जटिलताएं नहीं होंगी। असल में तथ्य यह है कि एक तानाशाह का मतलब है कि आपको स्थिर भाग को सेट में बदलने की आवश्यकता नहीं है (आप सभी (itertools.imap (dict.has_key, mylist)) को O (n) प्रदर्शन के साथ देख सकते हैं।
यन वर्नियर

मैं यह नहीं जानता कि यह (या सेटों पर निर्भर कोई अन्य समाधान) कैसे स्वीकार किया जा सकता है। प्रश्न सूचियों के बारे में है और मुझे स्पष्ट रूप से लगता है कि "सत्यापित करें कि क्या एक सूची दूसरे की उपसमुच्चय है" में सबसेट को शाब्दिक रूप से नहीं लिया जाना है। सेट करने के लिए रूपांतरण होने पर, डुप्लिकेट तत्वों पर कोई भी जानकारी खो जाती है, फिर भी, यदि प्रारंभिक सूची में वे शामिल हो सकते हैं, तो यह जाँचना महत्वपूर्ण हो सकता है कि क्या वे दूसरी सूची में दिखाई देते हैं और साथ ही साथ यह भी कहते हैं कि एक सूची के सभी तत्व मिल सकते हैं दूसरे के भीतर। सेट्स ऐसा नहीं करते हैं!
इनवर

प्रसंग मायने रखता है; यह पूछने वाले की मदद करने के लिए स्वीकार किया गया था, और भेद की व्याख्या की थी। हमें बताया गया कि उम्मीदवार सेट के रूप में प्रतिनिधित्व करने योग्य होंगे, इसलिए यह एक निर्धारित कार्य था। आपका मामला अलग हो सकता है, और आपके द्वारा उल्लिखित अंतर को संग्रह जैसे बहुस्तरीय का उपयोग करके हल किया जाएगा। मुठभेड़।
यान वर्नियर

140
>>> a = [1, 3, 5]
>>> b = [1, 3, 5, 8]
>>> c = [3, 5, 9]
>>> set(a) <= set(b)
True
>>> set(c) <= set(b)
False

>>> a = ['yes', 'no', 'hmm']
>>> b = ['yes', 'no', 'hmm', 'well']
>>> c = ['sorry', 'no', 'hmm']
>>> 
>>> set(a) <= set(b)
True
>>> set(c) <= set(b)
False

21
यह सबसे अच्छा दिखता है और सबसे सरल लिखता है, लेकिन सबसे तेज़ होना चाहिए set(a).issubset(b) क्योंकि इस मामले में आप केवल aसेट में परिवर्तित होते हैं b, लेकिन नहीं , जो समय बचाता है। आप timeitदो आदेशों में खपत समय की तुलना करने के लिए उपयोग कर सकते हैं । उदाहरण के लिए, timeit.repeat('set(a)<set(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000) और timeit.repeat('set(a).issubset(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
यूलान लियू

8
@YulanLiu: आप इसे तोड़ने के लिए नफरत करते हैं, लेकिन पहली बात issubsetयह है कि यदि तर्क a set/ है frozenset, तो यह जाँच करता है , और यदि ऐसा नहीं है, तो यह इसे setतुलना के लिए एक अस्थायी में बदल देता है , चेक चलाता है, फिर अस्थायी फेंक देता है setसमय के अंतर (यदि कोई हो), लेग लुकिंग लागतों में छोटे अंतर का एक कारक होगा ( setदूसरी बार किसी मौजूदा समय में विशेषता लुकअप की तुलना में अधिक महंगा है set), लेकिन यह ज्यादातर बड़े पर्याप्त आदानों के लिए धोना है।
शैडो रेंजर

3
यदि दोनों सूची में समान मान हैं, तो यह एक गलत वापसी करने जा रहा है, शर्त को सेट किया जाना चाहिए (a) <= सेट (b) इसके बजाय
ssi-aik

2
यह उत्तर सही कैसे हो सकता है। उन्होंने एक सूची नहीं एक सेट के लिए कहा। वे पूरी तरह से अलग हैं। क्या होगा अगर = [१, ३, ३, ५, ५] और बी = [१, ३, ३, ३, ५]। डुप्लिकेट के लिए सेट सिद्धांत अनुचित है।
एमानो केनी

1
मैं यह भी बताना चाहूंगा कि यदि a = [1,3,5] और b = [1,3,5], सेट (a) <सेट (b) गलत वापस आ जाएगा। आप इन मामलों को संभालने के लिए बराबर ऑपरेटर जोड़ सकते हैं: यानी सेट (ए) <= सेट (बी)।
जॉन

37
one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

all(x in two for x in one)

स्पष्टीकरण: जेनरेटर सूची की oneजाँच के माध्यम से लूपिंग बनाकर जाँचता है कि क्या वह सूची सूची में है two। यदि हर वस्तु सत्य है, तो all()वापस लौटता Trueहै False

एक लाभ यह भी है कि allहर वस्तु को संसाधित करने के बजाय एक लापता तत्व के पहले उदाहरण पर झूठी लौटाएं।


मुझे लगता है कि पठनीयता के लिए और आप जो हासिल करने की कोशिश कर रहे हैं उससे स्पष्ट है कि set(one).issubset(set(two))यह एक महान समाधान है। मेरे द्वारा पोस्ट किए गए समाधान के साथ आपको किसी भी ऑब्जेक्ट के साथ इसका उपयोग करने में सक्षम होना चाहिए, अगर उनके पास उचित तुलना ऑपरेटर परिभाषित हैं।
voidnologo

4
जनरेटर अभिव्यक्ति का उपयोग करें, न कि एक सूची समझ; पूर्व allशॉर्ट-सर्किट को ठीक से करने की अनुमति देगा , बाद वाला सभी चेक का प्रदर्शन करेगा, भले ही वह पहले चेक से स्पष्ट हो कि परीक्षण विफल हो जाएगा। पाने के लिए बस वर्ग कोष्ठक गिराएँ all(x in two for x in one)
शैडो रेंजर

क्या मैं गलत हूं, या आप स्थानीय लोगों के साथ इस पद्धति का उपयोग नहीं कर सकते हैं?
होमपर

22

यह मानते हुए कि आइटम हैशेबल हैं

>>> from collections import Counter
>>> not Counter([1, 2]) - Counter([1])
False
>>> not Counter([1, 2]) - Counter([1, 2])
True
>>> not Counter([1, 2, 2]) - Counter([1, 2])
False

यदि आप डुप्लिकेट आइटम जैसे के बारे में परवाह नहीं है। [1, 2, 2]और [1, 2]फिर बस उपयोग करें:

>>> set([1, 2, 2]).issubset([1, 2])
True

एक चौराहे के बाद छोटी सूची पर समानता का परीक्षण करना ऐसा करने का सबसे तेज़ तरीका है?

.issubsetइसे करने का सबसे तेज़ तरीका होगा। परीक्षण करने issubsetसे पहले लंबाई की जाँच करने से गति में सुधार नहीं होगा क्योंकि आपके पास अभी भी O (N + M) आइटम हैं, जिससे आप जाँच कर सकते हैं।


6

एक और समाधान एक का उपयोग करने के लिए किया जाएगा intersection

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(one).intersection(set(two)) == set(one)

सेट के चौराहे के होते हैं set one

(या)

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(one) & (set(two)) == set(one)

2
one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(x in two for x in one) == set([True])

अगर list1 सूची 2 में है:

  • (x in two for x in one)की सूची तैयार करता है True

  • जब हमारे पास set(x in two for x in one)केवल एक तत्व (ट्रू) होता है।


2

सेट सिद्धांत सूचियों के लिए अनुपयुक्त है क्योंकि सेट सिद्धांत का उपयोग करके डुप्लिकेट गलत उत्तर देगा।

उदाहरण के लिए:

a = [1, 3, 3, 3, 5]
b = [1, 3, 3, 4, 5]
set(b) > set(a)

कोई मतलब नहीं है। हां, यह एक गलत जवाब देता है लेकिन यह सही नहीं है क्योंकि सेट सिद्धांत सिर्फ तुलना कर रहा है: 1,3,5 बनाम 1,3,4,5। आपको सभी डुप्लिकेट शामिल करने होंगे।

इसके बजाय आपको प्रत्येक आइटम की प्रत्येक घटना को गिनना होगा और जांच के बराबर बड़ा करना होगा। यह बहुत महंगा नहीं है, क्योंकि यह ओ (एन ^ 2) संचालन का उपयोग नहीं कर रहा है और इसके लिए त्वरित प्रकार की आवश्यकता नहीं है।

#!/usr/bin/env python

from collections import Counter

def containedInFirst(a, b):
  a_count = Counter(a)
  b_count = Counter(b)
  for key in b_count:
    if a_count.has_key(key) == False:
      return False
    if b_count[key] > a_count[key]:
      return False
  return True


a = [1, 3, 3, 3, 5]
b = [1, 3, 3, 4, 5]
print "b in a: ", containedInFirst(a, b)

a = [1, 3, 3, 3, 4, 4, 5]
b = [1, 3, 3, 4, 5]
print "b in a: ", containedInFirst(a, b)

फिर इसे चलाने से आपको मिलता है:

$ python contained.py 
b in a:  False
b in a:  True

0

अगर मुझे पार्टी में देर हो रही हो तो क्षमा करें। ;)

यह जांचने के लिए कि क्या कोई set Aसबसेट है set B, Pythonहै A.issubset(B)और A <= B। यह setकेवल काम करता है और महान कार्य करता है लेकिन आंतरिक कार्यान्वयन की जटिलता अज्ञात है। संदर्भ: https://docs.python.org/2/library/sets.html#set-objects

मैं एक एल्गोरिथ्म के साथ जाँच करने के लिए आया था कि list Aक्या list Bनिम्नलिखित टिप्पणियों के साथ उपसमूह है ।

  • सबसेट खोजने की जटिलता को कम करने के लिए, मैं sortसबसे पहले दोनों सूचियों को उपयुक्त मानता हूँ ताकि उपसमुच्चय के लिए अर्हता प्राप्त करने वाले तत्वों की तुलना की जा सके।
  • इसने मेरी मदद breakकी loopजब दूसरी सूची B[j]के तत्व का मूल्य पहली सूची के तत्व से अधिक है A[i]
  • last_index_jशुरू करने के लिए प्रयोग किया जाता है loopसे अधिक list Bहै, जहां यह पिछले दूर छोड़ दिया। यह की शुरुआत से तुलना शुरू करने से बचने में मदद करता है list B(जो यह है कि आप अनावश्यक लगता है कि हो सकता है के रूप में, शुरू करने के लिए list Bसे index 0बाद में iterations।)
  • जटिलता O(n ln n)दोनों सूचियों को छाँटने के O(n)लिए और सबसेट के लिए जाँच के लिए प्रत्येक होगी ।
    O(n ln n) + O(n ln n) + O(n) = O(n ln n)

  • कोड में यह printदेखने के लिए बहुत सारे कथन हैं कि प्रत्येक iterationमें क्या चल रहा है loop। ये केवल समझने के लिए हैं।

जांचें कि क्या एक सूची किसी अन्य सूची की सबसेट है

is_subset = True;

A = [9, 3, 11, 1, 7, 2];
B = [11, 4, 6, 2, 15, 1, 9, 8, 5, 3];

print(A, B);

# skip checking if list A has elements more than list B
if len(A) > len(B):
    is_subset = False;
else:
    # complexity of sorting using quicksort or merge sort: O(n ln n)
    # use best sorting algorithm available to minimize complexity
    A.sort();
    B.sort();

    print(A, B);

    # complexity: O(n^2)
    # for a in A:
    #   if a not in B:
    #       is_subset = False;
    #       break;

    # complexity: O(n)
    is_found = False;
    last_index_j = 0;

    for i in range(len(A)):
        for j in range(last_index_j, len(B)):
            is_found = False;

            print("i=" + str(i) + ", j=" + str(j) + ", " + str(A[i]) + "==" + str(B[j]) + "?");

            if B[j] <= A[i]:
                if A[i] == B[j]:
                    is_found = True;
                last_index_j = j;
            else:
                is_found = False;
                break;

            if is_found:
                print("Found: " + str(A[i]));
                last_index_j = last_index_j + 1;
                break;
            else:
                print("Not found: " + str(A[i]));

        if is_found == False:
            is_subset = False;
            break;

print("subset") if is_subset else print("not subset");

उत्पादन

[9, 3, 11, 1, 7, 2] [11, 4, 6, 2, 15, 1, 9, 8, 5, 3]
[1, 2, 3, 7, 9, 11] [1, 2, 3, 4, 5, 6, 8, 9, 11, 15]
i=0, j=0, 1==1?
Found: 1
i=1, j=1, 2==1?
Not found: 2
i=1, j=2, 2==2?
Found: 2
i=2, j=3, 3==3?
Found: 3
i=3, j=4, 7==4?
Not found: 7
i=3, j=5, 7==5?
Not found: 7
i=3, j=6, 7==6?
Not found: 7
i=3, j=7, 7==8?
not subset

यदि आप उन्हें क्रमबद्ध करते हैं, तो सेट के बजाय किसी सूची का उपयोग करने का कोई कारण नहीं है ...
LtWorf

0

नीचे दिए गए कोड की जाँच करता है कि क्या दिया गया सेट दूसरे सेट का "उचित उपसमूह" है

 def is_proper_subset(set, superset):
     return all(x in superset for x in set) and len(set)<len(superset)


धन्यवाद @YannVernier मैंने उप और सुपरसेट दोनों के लिए खाली चेक को शामिल करने के लिए संशोधित किया है ताकि दोनों खाली होने पर यह गलत हो जाए।
लियो बैस्टिन

लेकिन आप ऐसा क्यों करते हैं? ए के लिए बी का एक सबसेट होने का मतलब है कि ए में कोई आइटम नहीं है जो बी में नहीं है, या समकक्ष, ए में सभी आइटम भी बी में हैं। इसलिए खाली सेट अपने आप सहित सभी सेटों का सबसेट है। आपकी अतिरिक्त जाँच यह दावा करती है कि यह नहीं है, और आप यह दावा करते हैं कि यह किसी भी तरह आदर्श है, लेकिन यह स्थापित शब्दावली के विपरीत है। फायदा क्या है?
यन वर्निअर

धन्यवाद @YannVernier अब कोड जांचता है कि क्या दिया गया सेट दूसरे सेट का "उचित उपसमूह" है या नहीं।
लियो बैस्टिन

यह उतना ही बुरा है जितना कि सेट के उपयोग पर भरोसा करने वाले उत्तर । गणितीय रूप से बोलते समय, एक सेट अलग-अलग तत्वों का एक संग्रह होता है, हम जाँच कर सकते हैं कि अगर एक सूची दूसरे का हिस्सा है, तो उस धारणा पर भरोसा नहीं करना चाहिए। यदि प्रारंभिक सूची में डुप्लिकेट शामिल थे, तो आपका फ़ंक्शन अभी भी सही लौटा सकता है , भले ही प्रश्न का तत्व दूसरी सूची में केवल एक बार मौजूद हो। मुझे नहीं लगता कि सूचियों की तुलना करने की कोशिश करते समय यह सही व्यवहार है।
inVader

0

अजगर 3.5 में आप [*set()][index]तत्व प्राप्त करने के लिए एक कर सकते हैं । यह अन्य विधियों की तुलना में बहुत धीमा समाधान है।

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

result = set(x in two for x in one)

[*result][0] == True

या सिर्फ लेन और सेट के साथ

len(set(a+b)) == len(set(a))

0

यहां बताया गया है कि मुझे कैसे पता चलेगा कि एक सूची दूसरे का सबसेट है, मेरे मामले में अनुक्रम मेरे लिए मायने रखता है।

def is_subset(list_long,list_short):
    short_length = len(list_short)
    subset_list = []
    for i in range(len(list_long)-short_length+1):
        subset_list.append(list_long[i:i+short_length])
    if list_short in subset_list:
        return True
    else: return False

0

अधिकांश समाधान मानते हैं कि सूचियों में डुप्लिकेट नहीं हैं। यदि आपकी सूचियों में डुप्लिकेट हैं, तो आप यह कोशिश कर सकते हैं:

def isSubList(subList,mlist):
    uniqueElements=set(subList)
    for e in uniqueElements:
        if subList.count(e) > mlist.count(e):
            return False     
    # It is sublist
    return True

यह सुनिश्चित करता है कि सूची या सामान्य तत्व से अधिक मात्रा में सबलिस्ट में अलग-अलग तत्व न हों।

lst=[1,2,2,3,4]
sl1=[2,2,3]
sl2=[2,2,2]
sl3=[2,5]

print(isSubList(sl1,lst)) # True
print(isSubList(sl2,lst)) # False
print(isSubList(sl3,lst)) # False

0

चूंकि किसी ने तार की तुलना करने पर विचार नहीं किया है, यहां मेरा प्रस्ताव है।

आप निश्चित रूप से जांचना चाहते हैं कि क्या पाइप ("|") या तो सूचियों का हिस्सा नहीं है और शायद स्वचालित रूप से एक और चरखा चुना गया है, लेकिन आपको यह विचार मिला।

खाली स्ट्रिंग का उपयोग करना विभाजक के रूप में एक समाधान नहीं है क्योंकि संख्याओं के कई अंक हो सकते हैं ([12,3]! = [1,23])

def issublist(l1,l2):
    return '|'.join([str(i) for i in l1]) in '|'.join([str(i) for i in l2])

-1

यदि आप पूछ रहे हैं कि क्या एक सूची दूसरी सूची में "निहित" है तो:

>>>if listA in listB: return True

यदि आप पूछ रहे हैं कि क्या listA में प्रत्येक तत्व में listB में मेल खाने वाले तत्वों की समान संख्या है:

all(True if listA.count(item) <= listB.count(item) else False for item in listA)

यह मेरे लिए काम नहीं करता है। रिटर्न झूठी भले ही लिस्टा == listB
Cass

@ कैस मैंने केवल स्ट्रिंग्स के साथ परीक्षण किया है। अपनी मशीन पर यह कोशिश करो। pastebin.com/9whnDYq4
DevPlayer

मैं "if listA में listA: return True" भाग की बात कर रहा था, दूसरे भाग की नहीं।
कैस

@ कैस पर विचार करें: ['एक', 'दो'] [, एक ',' दो '] में गलत फल लगते हैं। [[एक ’, 'दो’] [, एक ’,, दो’,] तीन ’में] गलत फल देता है। ['एक', 'दो'] में [['एक', 'दो'], 'तीन'] पैदावार सही है। तो हाँ अगर listA == ListB तो listB में listA हमेशा गलत लौटेगा क्योंकि listA को listB में सूची तत्व होना आवश्यक है। शायद आप सोच रहे हैं: listB में listA का अर्थ है "क्या listA में आइटम को listB में आइटम के रूप में सूचीबद्ध किया गया है। यह listB में listA का अर्थ नहीं है
DevPlayer

@ काश आह, मैं देखता हूं कि मेरी पोस्ट कैसे भ्रमित करती है। मूल पोस्ट को सूची के लिए परीक्षण करने के लिए कहा गया है जो सूची का सबसेट है। मूल पोस्ट के सवाल के आधार पर तकनीकी रूप से मेरी पोस्ट गलत है। इसके लिए सही होने के लिए प्रश्न "ifa में [item0, item2, listA, item3, listA,]" के लिए पूछना होगा। "'' ए ',' बी ',' सी '] [' डी ',' सी ',' एफ ',' ए ',' बी ',' ए '] में" आइटम नहीं "।
DevPlayer

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