如何使用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,因为它们的顺序不同。
下面的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
创建一个方法如何:
- 将搜索列表中的元素连接到一个字符串
- 将要搜索的列表中的元素连接到一个字符串
- 在第一个字符串中查找第二个字符串 的前词。
一样:
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接口,并且将枚举到索引。