Arrays 检查数组是否包含其他数组
我正在寻找一种方法来检查一个数组是否包含另一个数组的所有元素。 情况就是这样:我有两个字节数组Arrays 检查数组是否包含其他数组,arrays,vb.net,Arrays,Vb.net,我正在寻找一种方法来检查一个数组是否包含另一个数组的所有元素。 情况就是这样:我有两个字节数组bytes():一个包含文件的字节,另一个包含要比较的字节 例如,如果文件包含以下字节:4D 5A 90 00 03并且要比较的字符串是00 03,则我希望函数返回true。否则它显然会返回false。因此,要比较的字符串中的所有字节也必须存在于文件中 我已经在网上搜索过了。尝试了旧的goodContains()函数,但对于数组,它仅用于比较单个字节。你知道,一个字节太小,无法识别一个文件 如果可能的话
bytes()
:一个包含文件的字节,另一个包含要比较的字节
例如,如果文件包含以下字节:4D 5A 90 00 03
并且要比较的字符串是00 03
,则我希望函数返回true。否则它显然会返回false。因此,要比较的字符串中的所有字节也必须存在于文件中
我已经在网上搜索过了。尝试了旧的goodContains()
函数,但对于数组,它仅用于比较单个字节。你知道,一个字节太小,无法识别一个文件
如果可能的话,我想尽快完成
我正在使用VB.NET WinForms,VS 2013.NET 4.5.1
提前感谢,
白色
编辑:
现在我有一个列表(字节数())
如下:
00 25 85 69
00 41 52
00 78 96 32
这是三个Bytes()数组。如何检查我的文件字节数组是否包含所有这些值(文件必须包含00258569
、004152
和00789632
)?我已尝试使用此代码,但无效:
Dim BytesToCompare As List(Of Byte()) = StringToByteArray(S.Split(":")(3))
For Each B As Byte() In BytesToCompare
If FileBytes.All(Function(c) B.Contains(c)) Then
'Contains
TempResults.Add("T")
Else
TempResults.Add("F")
End If
Next
If CountResults(TempResults) Then
Return S
Exit For
End If
CountResults
中的代码如下:
Public Function CountResults(Input As List(Of String)) As Boolean
Dim TrueCount As Integer = 0
Dim FalseCount As Integer = 0
Dim TotalCount As Integer = Input.Count
For Each S In Input
If S = "T" Then
TrueCount = TrueCount + 1
ElseIf S = "F" Then
FalseCount = FalseCount + 1
End If
Next
If TrueCount = TotalCount Then
Return True
ElseIf FalseCount > TrueCount Then
Return False
End If
End Function
如果你不明白,请告诉我,我会尽力更好地解释
谢谢,
FWhite您可以使用
All
函数来检查它。它返回一个布尔值
Dim orgByteArray() As Byte = {CByte(1), CByte(2), CByte(3)}
Dim testByteArray() As Byte = {CByte(1), CByte(2)}
Dim result = orgByteArray.All(Function(b) testByteArray.Contains(b))
'output for this case returns False
用于将列表(Byte())
与Byte()
进行比较,其中Byte()
是列表(Byte())中所有子数组的完整列表。
我在想,也许除了蛮力法以外的其他方法会奏效,于是我发现了Boyer-Moore搜索算法
Public Class BoyerMooreSearch
' from C and Java code at http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
Private Shared Function SuffixLength(needle As Byte(), p As Integer) As Integer
Dim len As Integer = 0
Dim j = needle.Length - 1
Dim i = 0
While i >= 0 AndAlso needle(i) = needle(j)
i -= 1
j -= 1
len += 1
End While
Return len
End Function
Private Shared Function GetOffsetTable(needle As Byte()) As Integer()
Dim table(needle.Length - 1) As Integer
Dim lastPrefixPosition = needle.Length
For i = needle.Length - 1 To 0 Step -1
If Isprefix(needle, i + 1) Then
lastPrefixPosition = i + 1
End If
table(needle.Length - 1 - i) = lastPrefixPosition - i + needle.Length - 1
Next
For i = 0 To needle.Length - 2
Dim slen = SuffixLength(needle, i)
table(slen) = needle.Length - 1 - i + slen
Next
Return table
End Function
Private Shared Function Isprefix(needle As Byte(), p As Integer) As Boolean
Dim j = 0
For i = p To needle.Length - 1
If needle(i) <> needle(j) Then
Return False
End If
j += 1
Next
Return True
End Function
Private Shared Function GetCharTable(needle As Byte()) As Integer()
Const ALPHABET_SIZE As Integer = 256
Dim table(ALPHABET_SIZE - 1) As Integer
For i = 0 To table.Length - 1
table(i) = needle.Length
Next
For i = 0 To needle.Length - 2
table(needle(i)) = needle.Length - 1 - i
Next
Return table
End Function
Shared Function IndexOf(haystack As Byte(), needle As Byte()) As Integer
If needle.Length = 0 Then
Return 0
End If
Dim charTable = GetCharTable(needle)
Dim offsetTable = GetOffsetTable(needle)
Dim i = needle.Length - 1
While i < haystack.Length
Dim j = needle.Length - 1
While j >= 0 AndAlso haystack(i) = needle(j)
i -= 1
j -= 1
End While
If j < 0 Then
Return i + 1
End If
i += Math.Max(offsetTable(needle.Length - 1 - j), charTable(haystack(i)))
End While
Return -1
End Function
End Class
现在,我知道要匹配的字节序列在测试文件中(我确认通过使用十六进制编辑器搜索它们),并且假设(哦,天哪!)我正确地使用了另一种方法,后者不起作用,而我的方法起作用:
Boyer-Moore: True in 23913
LINQ: False in 3224
我还测试了OneFineDay的第一个代码示例,用于搜索要匹配的大小模式,并且在不到7或8个字节的情况下,该代码比Boyer Moore更快。因此,如果您想测试您正在搜索的数据的大小以及您正在寻找的模式的大小,Boyer Moore可能更适合您r“如果可能的话,我想尽快完成。”
编辑
除了OP对我建议的方法是否有效的不确定性之外,下面是一个非常小样本数据的测试:
Sub Test()
bytesToCheckFor = New List(Of Byte())
bytesToCheckFor.Add({0, 1}) ' the data to search for
bytesToCheckFor.Add({1, 2})
bytesToCheckFor.Add({0, 2})
Dim fileData As Byte() = {0, 1, 2} ' the file data
' METHOD 1: Boyer-Moore
Dim containsP As Boolean = True
For i = 0 To bytesToCheckFor.Count - 1
If BoyerMooreSearch.IndexOf(fileData, bytesToCheckFor(i)) = -1 Then
containsP = False
Exit For
End If
Next
Console.WriteLine("Boyer-Moore: {0}", containsP)
' METHOD 2: LINQ
Dim temp As New List(Of Byte)
Array.ForEach(bytesToCheckFor.ToArray, Sub(byteArray) Array.ForEach(byteArray, Sub(_byte) temp.Add(_byte)))
Dim result = fileData.All(Function(_byte) temp.Contains(_byte))
Console.WriteLine("LINQ: {0}", result)
Console.ReadLine()
End Sub
产出:
Boyer-Moore: False
LINQ: True
另外,我在最初的Main()方法中重命名了变量,希望能使它们更有意义。有一天,如果我有一个
列表(字节数()),会怎么样
,一个包含一些字节数组的列表。我如何检查文件是否包含字节数组主列表中包含的所有字节数组?非常感谢FWhiteDrill我使用了两个all
谓词,首先说使用所有数组,然后第二个all在检查所有数组时检查数组。您好,谢谢您的快速回答:)我将更新我的帖子,以便更好地描述我的问题,因为我不能用500个字符来描述……我应该写“FileBytes”而不是“byteList”(就像老例子一样?因为它告诉我一个错误:“All不是Byte的成员)我的示例显示了语法,使用你想要的名称。谢谢你,Andrew!这是一个非常详细的答案。我将在接下来的几天尝试一下。再次感谢你FWhiteHi@Andrew!由于OneFineDay提出的代码有点慢,我决定尝试你的代码,但没有很好的结果。你的代码搜索文件中的每个字节。这是不正确的:文件是T包含一个完整的字节段。例如:我们有一个三字节的文件:<代码> 00 01×02 /代码>。我们有一个字符串比较,这是代码> 00 02 < /代码>。您的代码返回true,因为实际上,文件包含“代码> 00”/代码>和<代码> 02 < /代码>。代码应该返回false,因为字节不在行中:事实上,在中间,有一个01
使搜索模式无效。再次感谢,FWhite@PWhite我刚刚用00 01 02
的示例文件数据和00 02
的搜索数据测试了我的代码。也许你把我的版本和另一个版本混淆了,因为我的版本有效,而另一个版本无效,或者我没有给出有意义的变量我会编辑我的答案来展示我是如何用你的样本数据测试它的。
Sub Test()
bytesToCheckFor = New List(Of Byte())
bytesToCheckFor.Add({0, 1}) ' the data to search for
bytesToCheckFor.Add({1, 2})
bytesToCheckFor.Add({0, 2})
Dim fileData As Byte() = {0, 1, 2} ' the file data
' METHOD 1: Boyer-Moore
Dim containsP As Boolean = True
For i = 0 To bytesToCheckFor.Count - 1
If BoyerMooreSearch.IndexOf(fileData, bytesToCheckFor(i)) = -1 Then
containsP = False
Exit For
End If
Next
Console.WriteLine("Boyer-Moore: {0}", containsP)
' METHOD 2: LINQ
Dim temp As New List(Of Byte)
Array.ForEach(bytesToCheckFor.ToArray, Sub(byteArray) Array.ForEach(byteArray, Sub(_byte) temp.Add(_byte)))
Dim result = fileData.All(Function(_byte) temp.Contains(_byte))
Console.WriteLine("LINQ: {0}", result)
Console.ReadLine()
End Sub
Boyer-Moore: False
LINQ: True