如何使用array搜索数组

本文关键字:数组 搜索 array 何使用 | 更新日期: 2023-09-27 18:08:11

我有两个字节数组:

    Dim A() As Byte = {1, 2, 3, 4, 5, 6, 7, 8, 9}
    Dim B() As Byte = {5, 6, 7}

现在我想找到A中完整B的出现次数。我试过Array。IndexOf(A, B)没有运气。有没有一种简单的方法来搜索数组数组不需要使用任何循环?

它应该以与B()相同的顺序找到5,6,7的索引(位置)。如果A()包含{1,2,3,4,7,6,5,9},它应该返回false或-1,因为它们的顺序不同。

如何使用array搜索数组

下面的Linq语句将给出一个包含b在a中的位置的IEnumerable<int>(如果不存在则为空集合):

Enumerable
    .Range( 0, 1 + a.Length - b.Length )
    .Where( i => a.Skip(i).Take(b.Length).SequenceEqual(b) );

我不知道如何翻译到VB.NET

这可能行得通,但这是c#,并且使用了循环:

private static int[] GetIndicesOf(byte[] needle, byte[] haystack)
{
    int[] foundIndices = new int[needle.Length];
    int found = 0;
    for (int i = 0; i < haystack.Length; i++)
    {
        if (needle[found] == haystack[i])
        {
            foundIndices[found++] = i;
            if (found == needle.Length)
                return foundIndices;
        }
        else
        {
            i -= found;   // Re-evaluate from the start of the found sentence + 1
            found = 0;    // Gap found, reset, maybe later in the haystack another occurrance of needle[0] is found
            continue;
        }
    }
    return null;            
}

测试输入:

Byte[] haystack = { 5, 6, 7, 8, 9, 0, 5, 6, 7 };
Byte[] needle = { 5, 6, 7 };
// Returns {0, 1, 2}
Byte[] haystack = { 5, 6, 0, 8, 9, 0, 5, 6, 7 };
Byte[] needle = { 5, 6, 7 };
// Returns {6, 7, 8}
Byte[] haystack = { 5, 6, 0, 7, 9, 0, 5, 6, 8 };
Byte[] needle = { 5, 6, 7 };
// Returns null
Byte[] haystack = { 1, 2, 1, 2, 2 };
Byte[] needle = { 1, 2, 2 };
// Returns {2, 3, 4}
Byte[] haystack = { 1, 2, 1, 2, 1, 2, 3 };
Byte[] needle = { 1, 2, 1, 2, 3 };
// Returns {2, 3, 4, 5, 6}
Byte[] haystack = { 1, 1, 1, 1, 2 };
Byte[] needle = { 1, 2 };
// Returns {3, 4}

但是Linq的@spender实现看起来更好。: - p

创建一个方法如何:

  1. 将搜索列表中的元素连接到一个字符串
  2. 将要搜索的列表中的元素连接到一个字符串
  3. 在第一个字符串中查找第二个字符串
  4. 的前词。

一样:

public bool IsSubSetOf(IList<int> list1, IList<int> list2){
   var string1 = string.Join("", list1);
   var string2 = string.Join("", list2);
   return string1.Contains(string2);
}

不是测试…

一般来说,解决这个问题的有效方法是KMP算法。快速搜索一下,可以在这里找到一个。net实现。它的实现伪代码可从维基百科获得。

下面的一个链接给出了一种低效但无害的易于编码的方法:

int[] T = new[]{1, 2, 3, 4, 5};
int[] P = new[]{3, 4};
for (int i = 0; i != T.Length; i++)
{
    int j = 0
    for (;i+j != T.Length && j != P.Length && T[i+j]==P[j]; j++);
    if (j == P.Length) return i;
}

我的看法是:

public static int Search<T>(T[] space, T[] searched) {
  foreach (var e in Array.FindAll(space, e => e.Equals(searched[0]))) {
    var idx = Array.IndexOf(space, e);
    if (space.ArraySkip(idx).Take(searched.Length).SequenceEqual(searched))
      return idx;
  }
  return -1;
}
public static class Linqy {
  public static IEnumerable<T> ArraySkip<T>(this T[] array, int index) {
    for (int i = index;  i < array.Length; i++) {
      yield return array[i];
    }
  }
}

一如既往,这取决于你的数据是否"足够好",或者你将不得不求助于更复杂但更有效的算法。我引入了arrayskip,因为Linq skip确实只假设IEnumerable接口,并且将枚举到索引。