假设我有一个包含数千个项目的大字符数组:
char[] mobyDick = "..."
,mobyDick.Length
= 2000。
我想知道该数组中是否存在某个字符数组,其中*是*。 (更新:我真的只需要知道它是否在主阵列中的某个索引之后。)
char[] test = {'a','b','c','d'}
我可以做类似
的事情char[] mobyDick = "..."
string mobyString = new string(mobyDick);
if (mobyString.Contains(new string(test)))
{ do stuff}
但这对我的情况来说不是最佳的,因为我正在尝试编写一个必须非常快速地工作的解析器,而且我不想每个字母左右创建和搜索字符串。
是否有某种方式(通过算法或通过某种.Net方法)找出mobyDick
作为char数组是否包含abcd
作为char数组?
答案 0 :(得分:2)
这看起来像一个有趣的问题,所以我开始创建一个扩展方法......
public static class ExtensionMethods
{
public static int ContainsArray(this char[] arrayToSearchIn, char[] arrayToFind)
{
if (arrayToFind.Length == 0)
return -1;
int lengthOfArrayToFInd = arrayToFind.Length;
int lengthOfArrayToSearchIn = arrayToSearchIn.Length;
for (int i = 0; i < lengthOfArrayToSearchIn; i++)
{
if (lengthOfArrayToSearchIn - i < lengthOfArrayToFInd)
return -1;
if (arrayToSearchIn[i] != arrayToFind[0])
continue;
int arrayToFindCounter = 0;
bool wasFound = true;
for (int j = i; j < i + lengthOfArrayToFInd; j++)
{
if (arrayToFind[arrayToFindCounter] == arrayToSearchIn[j])
arrayToFindCounter++;
else
{
wasFound = false;
break;
}
}
if (wasFound)
return i;
}
return -1;
}
}
这对我来说是使用任何长度子数组,包括空搜索 - 如果找到则返回第一个匹配的位置(从零开始),否则返回-1。
示例用法:
static void Main(string[] args)
{
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
char[] mobyDick = new[] {'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'd', 'a', 'z', 'y'};
char[] test = {'a', 'b', 'c', 'd'};
Console.WriteLine(mobyDick.ContainsArray(test)); // Position 12
Console.ReadLine();
}
答案 1 :(得分:1)
尝试一下:
private bool Contains(char[] mobyDick, char[] test)
{
for (int i = 0; i < mobyDick.Length - test.Length + 1; i++)
{
bool found = true;
for (int j = 0; j < test.Length; j++)
{
if (mobyDick[i + j] != test[j])
{
found = false;
break;
}
}
if (found) return true;
}
return false;
}
答案 2 :(得分:1)
我会尝试这种扩展方法:
public static bool ContainsChars(this char[] source, char[] target,out int index)
{
int targetLength = target.Length - 1;
int count = 0;
char currentCharToSearch = target[0];
for(int i=0; i<source.Length; i++)
{
if (source[i] == currentCharToSearch)
{
count++;
if (count == targetLength)
{
index = i - count + 1;
return true;
}
else
{
currentCharToSearch = target[count];
}
}
else
{
count = 0;
currentCharToSearch = target[0];
}
}
index = -1;
return false;
}
用法:
var c1 = new char[] { 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'h', 't' };
var c2 = new char[] { 'c', 'h', 't' };
int index;
var result = c1.ContainsChars(c2,out index); // true index = 6
c2 = new char[] { 'c', 't', 'h' };
var result2 = c1.ContainsChars(c2,out index); // false index = -1
答案 3 :(得分:1)
这是一个使用lambda查找搜索的所有有效“起点”的人。
//return first index of substring or -1 for not found
int searchForChar(char [] substring, char [] fulltext)
{
//all of the start points
var indices = fulltext.Select ((b,i) => b == substring.FirstOrDefault() ? i : -1)
.Where(i => i != -1).ToArray();
//search each start point
foreach (var index in indices)
{
var found = true;
int count = 0;
for(int i = index; i < index + substring.Length; i++)
{
found = true;
if(substring[count++] != fulltext[i])
{
found = false;
break;
}
}
if (found) return index;
}
return -1;
}
可能一种更高效的方式就像你在原始问题中所做的那样。
int searchForChar(char [] substring, char [] fulltext)
{
return fulltext.ToString().IndexOf(substring.ToString());
}
答案 4 :(得分:0)
for循环如何首先在大数组中搜索测试用例的第一个字符,然后将测试数组中的连续字符与大数组的连续成员进行比较?
答案 5 :(得分:0)
对于记录,这是使用通用扩展方法的另一种解决方案。它适用于任何实现IComparable的数组类型。
void Main()
{
var c1 = new char[] { 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'h', 't' };
var c2 = new char[] { 'c', 'h', 't' };
if (c1.Contains(c2))
{
// do something
}
int i = c1.IndexOf(c2);
}
public static class ArrayExtensions
{
public static bool Contains<T>(this T[] array, T[] subarray) where T : IComparable
{
return array.IndexOf(subarray) >= 0;
}
public static int IndexOf<T>(this T[] array, T[] subarray) where T : IComparable
{
for (int i = 0; i < array.Length - subarray.Length + 1; i++)
{
bool found = true;
for (int j = 0; j < subarray.Length; j++)
{
if (array[i + j].CompareTo(subarray[j]) != 0)
{
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
}
答案 6 :(得分:-2)
使用此:
var search = mobyDick.Intersect(test);
if (search.ToArray().Length > 0)
{
//do something
}