जांचें कि क्या कोई सरणी दूसरे का सबसेट है


145

यह जाँचने के बारे में कोई विचार है कि क्या वह सूची दूसरे की सबसेट है?

विशेष रूप से, मेरे पास है

List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };

LINQ का उपयोग करके यह कैसे जांचें कि t2 t1 का सबसेट है?


यदि सूचियों को क्रमबद्ध किया गया है (जैसा कि आपके उदाहरण में), यह O (n + m) समय में संभव होना चाहिए।
कर्नल पैनिक

जवाबों:


255
bool isSubset = !t2.Except(t1).Any();

1
मैंने विस्तार विधि geekswithblogs.net/mnf/archive/2011/05/13/…
माइकल फ्रीजिम

@Bul Ikana इस कोड का कार्य सरल है, विस्तार विधि आंतरिक रूप से बराबरी वाली ऑब्जेक्ट क्लास विधियों के समान और गेटहैशकोड को कॉल करती है यदि नौकरी के लिए कोई IEqualityComparer प्रदान नहीं किया गया है।
मृणाल कंबोज

2
यदि सूचियाँ लंबाई n और m हैं, तो इस एल्गोरिथ्म की समय जटिलता क्या है?
कर्नल पैनिक

2
अच्छा होगा यदि यह एक linq विधि के लिए उबला हुआ था, जिसे ContainsAll कहा जाता है
सेबस्टियन पैटन

60

सेट के साथ काम करने पर सूची के बजाय हैशसेट का उपयोग करें। तो आप बस IsSubsetOf () का उपयोग कर सकते हैं

HashSet<double> t1 = new HashSet<double>{1,3,5};
HashSet<double> t2 = new HashSet<double>{1,5};

bool isSubset = t2.IsSubsetOf(t1);

क्षमा करें कि यह LINQ का उपयोग नहीं करता है। :-(

यदि आपको सूचियों का उपयोग करने की आवश्यकता है, तो @ जारेड का समाधान कैविएट के साथ काम करता है जिसे आपको किसी भी दोहराया तत्वों को हटाने की आवश्यकता होगी जो मौजूद हैं।


3
बिल्कुल सही। आप एक सेट ऑपरेशन चाहते हैं, उनके लिए डिज़ाइन किए गए वर्ग का उपयोग करें। कैमरन का समाधान रचनात्मक है, लेकिन हशसेट की तरह स्पष्ट / अभिव्यक्त नहीं है।
टेक्नोफाइल

2
उम मैं असहमत हूं क्योंकि सवाल विशेष रूप से "LINQ का उपयोग करें" कहता है।
JaredPar

9
@JaredPar: तो क्या? क्या किसी को उस रास्ते से सही रास्ता दिखाना बेहतर नहीं है जिस तरह से वे जाना चाहते हैं?
जोनाथन एलेन

एक सूची अपना क्रम बनाए रखती है लेकिन एक सेट ऐसा नहीं करता है। यदि आदेश महत्वपूर्ण है तो यह गलत परिणाम देगा।
UUDdLrLrSs

11

यदि आप इकाई-परीक्षण कर रहे हैं तो आप CollectionAssert.IsSubsetOf विधि का भी उपयोग कर सकते हैं :

CollectionAssert.IsSubsetOf(subset, superset);

उपरोक्त मामले में इसका मतलब होगा:

CollectionAssert.IsSubsetOf(t2, t1);

7

यह यहां तैनात अन्य लोगों की तुलना में काफी अधिक कुशल समाधान है, विशेष रूप से शीर्ष समाधान:

bool isSubset = t2.All(elem => t1.Contains(elem));

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

bool isSubset = true;
foreach (var element in t2) {
    if (!t1.Contains(element)) {
        isSubset = false;
        break;
    }
}

मैंने सभी समाधानों के कुछ अल्पविकसित प्रदर्शन विश्लेषण किया, और परिणाम बहुत कठोर हैं। ये दोनों समाधान .Except () और .Intersect () समाधानों की तुलना में लगभग 100x तेज़ हैं, और अतिरिक्त मेमोरी का उपयोग नहीं करते हैं।


ठीक यही !t2.Except(t1).Any()तो कर रहा है। Linq आगे पीछे काम कर रहा है। Any()पूछ रहा है IEnumerableकि क्या कम से कम एक तत्व है। इस परिदृश्य t2.Except(t1)में केवल पहले तत्व का उत्सर्जन हो रहा है t2जो अंदर नहीं है t1। के पहले तत्व हैं t2में नहीं है t1यह सबसे तेजी से खत्म, अगर के सभी तत्वों t2में हैं t1यह सबसे लंबे समय तक चलता है।
बजे

किसी तरह के बेंचमार्क के साथ खेलने के दौरान, मुझे पता चला, जब आप लेते हैं t1={1,2,3,...9999}और t2={9999,9998,99997...9000}, आपको निम्नलिखित माप मिलते हैं !t2.Except(t1).Any(): 1ms -> t2.All(e => t1.Contains(e)): 702ms:। और यह सीमा जितनी बड़ी होती जाती है।
abto

2
यह लिनक के काम करने का तरीका नहीं है। t2.Except (t1)एक लौटा रहा है IEnumerableनहीं एक Collection। यह तभी संभव आइटम के सभी का उत्सर्जन करता है, तो आप पूरी तरह से इस पर उदाहरण के लिए पुनरावृति, ToArray ()या ToList ()या उपयोग foreachके अंदर तोड़ने के बिना। उस अवधारणा के बारे में अधिक पढ़ने के लिए लाइनक आस्थगित निष्पादन के लिए खोजें ।
abto

1
मैं पूरी तरह से अवगत हूं कि लाइनक में आस्थगित निष्पादन कैसे काम करता है। आप अपनी इच्छानुसार निष्पादन को स्थगित कर सकते हैं, लेकिन जब आप यह निर्धारित करना चाहते हैं कि क्या t2 t1 का सबसेट है, तो आपको यह पता लगाने के लिए पूरी सूची को पुनरावृत्त करना होगा। उस तथ्य के आसपास कोई नहीं मिल रहा है।
user2325458

2
अपनी टिप्पणी से उदाहरण लेते हैं t2={1,2,3,4,5,6,7,8} t1={2,4,6,8} t2.Except(t1)=> t2 का पहला तत्व = 1 => 1 से t1 का अंतर 1 है ({2,4,6,8} के खिलाफ जाँच) => Except()प्रथम तत्व का उत्सर्जन करता है 1 => Any()एक तत्व => प्राप्त करता है Any()t2 में तत्वों की सही जाँच नहीं होने पर परिणाम सत्य है।
abto

6

@ एक्सटेंशन विधि के रूप में कैमरन का समाधान:

public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return !a.Except(b).Any();
}

उपयोग:

bool isSubset = t2.IsSubsetOf(t1);

(यह समान है, लेकिन @ माइकल के ब्लॉग पर पोस्ट किए गए के समान नहीं है)


0

@Cameron और @Neil से उत्तरों पर निर्माण मैंने एक विस्तार विधि लिखी है जो कि एन्यूमरेबल क्लास के समान शब्दावली का उपयोग करती है।

/// <summary>
/// Determines whether a sequence contains the specified elements by using the default equality comparer.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">A sequence in which to locate the values.</param>
/// <param name="values">The values to locate in the sequence.</param>
/// <returns>true if the source sequence contains elements that have the specified values; otherwise, false.</returns>
public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> values)
{
    return !values.Except(source).Any();
}

0

यहाँ हम जाँचते हैं कि यदि बाल सूची (अर्थात t2) में कोई तत्व मौजूद है जो मूल सूची (अर्थात t1) द्वारा सम्‍मिलित नहीं है । यदि ऐसा कोई मौजूद नहीं है तो सूची दूसरे के सबसेट है।

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

bool isSubset = !(t2.Any(x => !t1.Contains(x)));

-1

इसे इस्तेमाल करे

static bool IsSubSet<A>(A[] set, A[] toCheck) {
  return set.Length == (toCheck.Intersect(set)).Count();
}

यहाँ विचार यह है कि Intersect केवल उन मानों को लौटाएगा जो दोनों Arrays में हैं। इस बिंदु पर यदि परिणामी सेट की लंबाई मूल सेट के समान है, तो "सेट" के सभी तत्व "चेक" में भी हैं और इसलिए "सेट" "टॉच" का सबसेट है।

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

संकेत: मैंने कैमरन के जवाब के लिए मतदान किया।


4
यह काम करता है अगर वे वास्तव में सेट होते हैं, लेकिन नहीं अगर दूसरे "सेट" में दोहराया तत्व शामिल हैं क्योंकि यह वास्तव में एक सूची है। यह सुनिश्चित करने के लिए कि आप शब्दार्थ सेट कर चुके हैं, आप हाशसेट <डबल> का उपयोग कर सकते हैं।
tvanfosson 3

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