2011-02-01 38 views
5

Cách đơn giản nhất để tìm một byte [] bên trong một byte [] khác là gì? tôi có một cảm giác tôi có thể làm điều đó với LINQ nhưng tôi không biết làm thế nào.Tìm một mảng (byte []) bên trong một mảng khác?

Lưu ý: Tôi đã thực hiện tìm kiếm với [c#] và không tìm thấy bất cứ điều gì, tôi ngạc nhiên.

+0

Tôi nghĩ chúng tôi cần thêm thông tin. Bạn đang cố gắng tìm một chuỗi byte trong một mảng byte? Bạn có thể đưa ra một ví dụ? – Andrew

+2

Xem, ví dụ: thuật toán [Knuth-Morris-Pratt] (http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm). – jason

Trả lời

7

Đây là một cách (ngây thơ?) Đơn giản để làm điều đó:

static int search(byte[] haystack, byte[] needle) 
{ 
    for (int i = 0; i <= haystack.Length - needle.Length; i++) 
    { 
     if (match(haystack, needle, i)) 
     { 
      return i; 
     } 
    } 
    return -1; 
} 

static bool match(byte[] haystack, byte[] needle, int start) 
{ 
    if (needle.Length + start > haystack.Length) 
    { 
     return false; 
    } 
    else 
    { 
     for (int i = 0; i < needle.Length; i++) 
     { 
      if (needle[i] != haystack[i + start]) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
} 
+0

Hoàn hảo, giống như tôi cần. Để xấu tôi không thể làm điều này với LINQ hoặc một cái gì đó được xây dựng in Bạn đã chỉ cần viết này ngay bây giờ? hoặc sao chép/dán nó từ đâu đó? –

+0

Lưu ý rằng tùy thuộc vào đầu vào, điều này có khả năng rất chậm. – jason

+0

@acidzombie - Chỉ cần viết nó. @ Jason - vâng có thể chậm, nhưng đơn giản. – Ergwun

-2

bạn có thể đã tự tìm ra điều này nhưng đôi khi tôi thích làm điều đơn giản.

bool found = false; 
int i = 0; 
for(; i < byteArray.Length || found; i++) 
{ 
    if(byteArray[i] == lookingFor) 
    { 
    found = true; 
    } 
} 
+2

Tôi nghĩ bạn hiểu sai câu hỏi. Hãy suy nghĩ về câu hỏi khi tìm một từ trong một chuỗi, nhưng từ đó là một 'byte []' và chuỗi là một 'byte []' khác. – jason

+0

yeah tôi đọc nó như là byte trong một mảng byte. lỗi của tôi. nếu bạn có ascii, bạn có thể sử dụng ASCIIEncoding.ASCII.GetString để tạo một chuỗi từ byte của bạn [] –

0

Hãy thử này với việc sử dụng các biểu thức lambda:

private bool CheckPatternInArray(byte[] array, byte[] pattern) 
{ 
    int fidx = 0; 
    int result = Array.FindIndex(array, 0, array.Length, (byte b) => 
      { 
       fidx = (b == pattern[fidx]) ? fidx + 1 : 0; 
       return (fidx == pattern.Length); 
      }); 
    return (result >= pattern.Length - 1); 
} 

Nếu bạn đang theo đuổi những nhanh nhất, kiểm tra các giải pháp here.

18

Dưới đây là một phiên bản nhanh hơn của Ergwun's excellent answer:

static int SearchBytes(byte[] haystack, byte[] needle) { 
    var len = needle.Length; 
    var limit = haystack.Length - len; 
    for(var i = 0; i <= limit; i++) { 
     var k = 0; 
     for(; k < len; k++) { 
      if(needle[k] != haystack[i+k]) break; 
     } 
     if(k == len) return i; 
    } 
    return -1; 
} 

Trong một thử nghiệm ngắn với một đống cỏ khô 11MB và 9 byte kim, đây là nhanh hơn khoảng ba lần.

Các tối ưu là:

  • Không có chức năng cuộc gọi mỗi lần thông qua các vòng ngoài.
  • Độ dài của kim và giới hạn tìm kiếm được lưu trong bộ nhớ cache.
  • Kiểm tra độ dài dư thừa ở đầu match() bị xóa.

Tất nhiên đối với mảng byte dài bạn muốn sử dụng cái gì đó như tìm kiếm Boyer-Moore, nhưng với nhiều mục đích, một thuật toán đơn giản như thế này đủ tốt và có đặc điểm ngắn gọn và dễ hiểu và xác minh.

Các vấn đề liên quan