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。因此,要比较的字符串中的所有字节也必须存在于文件中

我已经在网上搜索过了。尝试了旧的good
Contains()
函数,但对于数组,它仅用于比较单个字节。你知道,一个字节太小,无法识别一个文件

如果可能的话,我想尽快完成

我正在使用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