2011-09-06 22 views
6

मुझे अन्य बड़े अनुक्रम में अनुक्रम खोजने की आवश्यकता है, उदाहरण के लिए, {1,3,2,3}{1,3,2,3,4,3} और {5,1,3,2,3} में मौजूद है। क्या IEnumerable या कुछ और के साथ इसे जल्दी करने का कोई तरीका है?लंबे अनुक्रम में एक अनुक्रम ढूँढना

+1

एक में अनुक्रम है int सरणी, या सिर्फ एक अल्पविराम सीमित स्ट्रिंग? –

+0

वास्तव में यह एक सूची है जिसे सरणी में परिवर्तित किया जा सकता है। – user906763

+0

क्या आप सिर्फ यह जांचना चाहते हैं कि अनुक्रम एक अनुक्रम में है और सत्य/गलत वापस आ गया है? – BoltClock

उत्तर

1

आप शुरू करने के लिए इस तरह कुछ कोशिश कर सकते हैं। ,

if (String.Join(",", numericList.ConvertAll<string>(x => x.ToString()).ToArray()) 
{ 
    //get sequence 
} 
5

इस विधि एक माता पिता के अनुक्रम में किसी परिणाम मिलेगा किसी भी प्रकार Equals() के माध्यम से तुलना की जा सकती है कि: एक बार जब आप एक स्ट्रिंग के लिए इस सूची परिवर्तित कर दिया है, तो आप में प्रयोग करने से अनुक्रम पा सकते हैं

public static bool ContainsSubequence<T>(this IEnumerable<T> parent, IEnumerable<T> target) 
{ 
    bool foundOneMatch = false; 
    using (IEnumerator<T> parentEnum = parent.GetEnumerator()) 
    { 
     using (IEnumerator<T> targetEnum = target.GetEnumerator()) 
     { 
      // Get the first target instance; empty sequences are trivially contained 
      if (!targetEnum.MoveNext()) 
       return true; 

      while (parentEnum.MoveNext()) 
      { 
       if (targetEnum.Current.Equals(parentEnum.Current)) 
       { 
        // Match, so move the target enum forward 
        foundOneMatch = true; 
        if (!targetEnum.MoveNext()) 
        { 
         // We went through the entire target, so we have a match 
         return true; 
        } 
       } 
       else if (foundOneMatch) 
       { 
        return false; 
       } 
      } 

      return false; 
     } 
    } 
} 

आप इस तरह इसका इस्तेमाल कर सकते हैं: यह मान लिया गया है

bool match = new[] {1, 2, 3}.ContainsSubsequence(new[] {1, 2}); // match == true 
match = new[] {1, 2, 3}.ContainsSubsequence(new[] {1, 3}); // match == false 

ध्यान दें कि लक्ष्य अनुक्रम कोई null तत्व है।

अद्यतन: upvotes, हर किसी के लिए धन्यवाद, लेकिन इसके बाद के संस्करण कोड में वास्तव में है एक बग! यदि कोई आंशिक मिलान मिलता है, लेकिन फिर पूर्ण मिलान में नहीं आता है, तो प्रक्रिया रीसेट करने के बजाय समाप्त हो गई है (जिसे {1, 2, 1, 2, 3}.ContainsSubsequence({1, 2, 3}) जैसे किसी पर लागू होने पर स्पष्ट रूप से गलत किया गया है)।

ऊपर कोड परिणाम को के अधिक सामान्य परिभाषा के लिए वास्तव में अच्छी तरह से काम करता है (अर्थात contiguousness की आवश्यकता नहीं है), लेकिन आदेश को रीसेट को संभालने के लिए (जो सबसे IEnumerators का समर्थन नहीं करते) लक्ष्य अनुक्रम सामने प्रगणित किए जाने की आवश्यकता है। यही कारण है कि निम्नलिखित कोड की ओर जाता है:

public static bool ContainsSubequence<T>(this IEnumerable<T> parent, IEnumerable<T> target) 
{ 
    bool foundOneMatch = false; 
    var enumeratedTarget = target.ToList(); 
    int enumPos = 0; 

    using (IEnumerator<T> parentEnum = parent.GetEnumerator()) 
    { 
     while (parentEnum.MoveNext()) 
     { 
      if (enumeratedTarget[enumPos].Equals(parentEnum.Current)) 
      { 
       // Match, so move the target enum forward 
       foundOneMatch = true; 
       if (enumPos == enumeratedTarget.Count - 1) 
       { 
        // We went through the entire target, so we have a match 
        return true; 
       } 

       enumPos++; 
      } 
      else if (foundOneMatch) 
      { 
       foundOneMatch = false; 
       enumPos = 0; 

       if (enumeratedTarget[enumPos].Equals(parentEnum.Current)) 
       { 
        foundOneMatch = true; 
        enumPos++; 
       } 
      } 
     } 

     return false; 
    } 
} 

इस कोड को किसी भी कीड़े नहीं है, लेकिन बड़े (या अनंत) दृश्यों के लिए अच्छी तरह से काम नहीं करेगा।

+1

क्या आपने अपने उदाहरण में गलती की? 1, 3 अनुक्रम 1, 2, 3 में कैसे है? दोनों संख्याएं मौजूद हैं, लेकिन अनुक्रम में नहीं। ऐसा लगता है कि आपकी विधि निर्धारित करती है कि ऑर्डर या अनुक्रम के संबंध में संख्याएं मौजूद हैं या नहीं। –

+0

@ जेम्स जैसा कि मैंने अंत में उल्लेख किया है, यह गैर-संगत अनुवर्तीताओं (उदाहरण के लिए, '{1, 2, 3} के लिए अनुमति देता है। Contquence ({2, 1, 3}) == false'।) जैसा कि मैं भी अंत में उल्लेख करें, उस स्थिति को आसानी से लगाया जाता है, इसकी आवश्यकता होनी चाहिए। आम तौर पर बाद के बारे में बात करते समय, संगतता * नहीं * आवश्यक होती है (उदाहरण के लिए, सबसे आम आम अनुक्रम समस्या देखें।) – dlev

+0

इसे गैर-संगत अनुवर्तीताओं की अनुमति नहीं देनी चाहिए। – user906763

4

@ dlev के लिए इसी तरह की है, लेकिन यह भी संभालती {1,1,1,2}.ContainsSubsequence({1,1,2})

public static bool ContainsSubsequence<T>(this IEnumerable<T> parent, IEnumerable<T> target) 
{ 
    var pattern = target.ToArray(); 
    var source = new LinkedList<T>(); 
    foreach (var element in parent) 
    { 
     source.AddLast(element); 
     if(source.Count == pattern.Length) 
     { 
      if(source.SequenceEqual(pattern)) 
       return true; 
      source.RemoveFirst(); 
     } 
    } 
    return false; 
} 
+1

+1 ब्रेवटी, मेटेक्स, मेथेंक्स मेल करता है ... –

+0

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

0

यह मैं

var a1 = new List<int> { 1, 2, 3, 4, 5 }; 
var a2 = new List<int> { 2, 3, 4 }; 

int index = -1; 
bool res = a2.All(
    x => index != -1 ? (++index == a1.IndexOf(x)) : ((index = a1.IndexOf(x)) != -1) 
); 
+0

आपका समाधान सबसे सुरुचिपूर्ण लगता है लेकिन इसे 'ए 1 = नई सूची {1, 2, 9, 1, 2, 3, 4, 5}' और 'ए 2 = नई सूची {2, 3, 4}' बजाय; यह भी प्रयास करें कि 'a1' में इस नए मान के साथ स्वयं शामिल है - यह मेरे लिए काम नहीं करता है। – user2341923

0

यह फ़ंक्शन जांच के लिए काम करता है कि क्या सूची parent कुछ LINQ का उपयोग कर सूची target शामिल हैं:

public static bool ContainsSequence<T>(this List<T> parent, List<T> target) 
    { 
     for (int fromElement = parent.IndexOf(target.First()); 
      (fromElement != -1) && (fromElement <= parent.Count - target.Count); 
      fromElement = parent.FindIndex(fromElement + 1, p => p.Equals(target.First()))) 
     { 
      var comparedSequence = parent.Skip(fromElement).Take(target.Count); 
      if (comparedSequence.SequenceEqual(target)) return true; 
     } 
     return false; 
    }  
1

यदि आप सरल serializable हैंडलिंग कर रहे हैं प्रकार, आपको लगता है कि काफी आसानी से कर अगर आप स्ट्रिंग के लिए सरणियों में बदल सकते हैं:

public static bool ContainsList<T>(this List<T> containingList, List<T> containedList) 
{ 
    string strContaining = "," + string.Join(",", containingList) + ","; 
    string strContained = "," + string.Join(",", containedList) + ","; 
    return strContaining.Contains(strContained); 
} 

नोट एक विस्तार विधि है कि, तो आप इसे पसंद कॉल करने के लिए सक्षम हो जाएगा:

if (bigList.ContainsList(smallList)) 
{ 
    ... 
} 
संबंधित मुद्दे