2013-04-20 5 views
6

खोजें

List<byte> lbyte 

byte[] searchBytes 

मैं न केवल एक एकल बाइट के लिए लेकिन searchBytes के सूचकांक के लिए lbyte खोज कैसे कर सकते हैं है है?
ईजी।

Int32 index = lbyte.FirstIndexOf(searchBytes); 

यहां पर बलवान बल है जिसके साथ मैं आया हूं।
मैं जो प्रदर्शन ढूंढ रहा हूं वह नहीं।

public static Int32 ListIndexOfArray(List<byte> lb, byte[] sbs) 
{ 
    if (sbs == null) return -1; 
    if (sbs.Length == 0) return -1; 
    if (sbs.Length > 8) return -1; 
    if (sbs.Length == 1) return lb.FirstOrDefault(x => x == sbs[0]); 
    Int32 sbsLen = sbs.Length; 
    Int32 sbsCurMatch = 0; 
    for (int i = 0; i < lb.Count; i++) 
    { 
     if (lb[i] == sbs[sbsCurMatch]) 
     { 
      sbsCurMatch++; 
      if (sbsCurMatch == sbsLen) 
      { 
       //int index = lb.FindIndex(e => sbs.All(f => f.Equals(e))); // fails to find a match 
       IndexOfArray = i - sbsLen + 1; 
       return; 
      } 
     } 
     else 
     { 
      sbsCurMatch = 0; 
     } 
    } 
    return -1; 
} 
+0

"lbyte" क्या है के साथ कर सकता है? –

+0

बाइट – Paparazzi

+0

@YairNevet की एक सूची बाइट्स की एक और सूची @YairNevet, इस अनिवार्य है यहाँ orderedlist.containssequence वहाँ होना चाहिए एक अच्छा समाधान के रूप में अपनी अनिवार्य रूप से string.contains के साथ हल किया लेकिन यह एक अधिक सामान्य मामले [यहां] देखने का प्रयास करें –

उत्तर

3

आपको यहां Boyer-Moore algorithm उपयोगी मिल सकता है। अपनी सूची को एक सरणी में खोजें और खोजें। एल्गोरिदम कोड this post से लिया गया है।

static int SimpleBoyerMooreSearch(byte[] haystack, byte[] needle) 
{ 
    int[] lookup = new int[256]; 
    for (int i = 0; i < lookup.Length; i++) { lookup[i] = needle.Length; } 

    for (int i = 0; i < needle.Length; i++) 
    { 
     lookup[needle[i]] = needle.Length - i - 1; 
    } 

    int index = needle.Length - 1; 
    var lastByte = needle.Last(); 
    while (index < haystack.Length) 
    { 
     var checkByte = haystack[index]; 
     if (haystack[index] == lastByte) 
     { 
      bool found = true; 
      for (int j = needle.Length - 2; j >= 0; j--) 
      { 
       if (haystack[index - needle.Length + j + 1] != needle[j]) 
       { 
        found = false; 
        break; 
       } 
      } 

      if (found) 
       return index - needle.Length + 1; 
      else 
       index++; 
     } 
     else 
     { 
      index += lookup[checkByte]; 
     } 
    } 
    return -1; 
} 

फिर आप इस तरह खोज सकते हैं। यदि lbyte एक निश्चित समय के बाद स्थिर रहेगा, तो आप इसे एक बार सरणी में परिवर्तित कर सकते हैं और उसे पास कर सकते हैं।

//index is returned, or -1 if 'searchBytes' is not found 
int startIndex = SimpleBoyerMooreSearch(lbyte.ToArray(), searchBytes); 

टिप्पणी के आधार पर अद्यतन। यहाँ IList कार्यान्वयन जिसका अर्थ है कि सरणियों और सूची (और बाकी है कि IList लागू करता है कुछ भी पारित किया जा सकता)

static int SimpleBoyerMooreSearch(IList<byte> haystack, IList<byte> needle) 
{ 
    int[] lookup = new int[256]; 
    for (int i = 0; i < lookup.Length; i++) { lookup[i] = needle.Count; } 

    for (int i = 0; i < needle.Count; i++) 
    { 
     lookup[needle[i]] = needle.Count - i - 1; 
    } 

    int index = needle.Count - 1; 
    var lastByte = needle[index]; 
    while (index < haystack.Count) 
    { 
     var checkByte = haystack[index]; 
     if (haystack[index] == lastByte) 
     { 
      bool found = true; 
      for (int j = needle.Count - 2; j >= 0; j--) 
      { 
       if (haystack[index - needle.Count + j + 1] != needle[j]) 
       { 
        found = false; 
        break; 
       } 
      } 

      if (found) 
       return index - needle.Count + 1; 
      else 
       index++; 
     } 
     else 
     { 
      index += lookup[checkByte]; 
     } 
    } 
    return -1; 
} 

के बाद से सरणियों और सूचियों IList लागू है, वहाँ कोई रूपांतरण आवश्यक है जब वह अपने मामले में बुला रहे हैं।

int startIndex = SimpleBoyerMooreSearch(lbyte, searchBytes); 
+1

+1 @ स्कॉटकैम्बरलेन, महान सुझाव। –

+0

बनाने के लिए सक्षम हो सकता है – keyboardP

+0

अनजाने में सूची प्रत्येक कॉल के साथ बदलती है। मैं अभी तक इसका पालन नहीं करता लेकिन मैं इसे आज़मा दूंगा। आप IList संस्करण लागू करते हैं तो इसे यहाँ पोस्ट करें। – Paparazzi

4

ब्रूट फोर्स हमेशा एक विकल्प होता है। हालांकि कुछ अन्य तरीकों की तुलना में धीमी गति से, अभ्यास में यह आमतौर पर बहुत बुरा नहीं होता है। lbyte बहुत बड़ा नहीं है और इसमें पैथोलॉजिकल डेटा नहीं है, इसे कार्यान्वित करना और काफी स्वीकार्य है।

यह brute force string searching जैसा ही अवधारणा है।

1

एक और तरीका है आप लैम्ब्डा अभिव्यक्ति

int index = lbyte.FindIndex(e => searchBytes.All(i => i.Equals(e)); 
+0

गुम है) और मैंने परीक्षण किया कि यह मैच नहीं ढूंढता है। – Paparazzi

+0

क्या आप अपना टेस्ट केस लिखेंगे? –

+0

मैंने जोड़ा जहां मैं प्रश्न में पोस्ट किए गए कोड पर इसका परीक्षण कर रहा हूं। मेरे पास डेटा बनाने के लिए वास्तव में "परीक्षण केस" नहीं है। मैं डेटाबेस से उन बाइट्स पढ़ रहा हूँ। लेकिन मुझे पता है कि ब्रूट फोर्स ठीक से मेल खाता है। – Paparazzi

संबंधित मुद्दे