C# 查找子数组工具类
/// <summary>
/// Code shared to do searches
/// </summary>
public class SubarrayUtils
{
/// <summary>
/// Code shared by ArraySegment to do searches.
/// The source is the ArraySegment being searched, and the target is the ArraySegment being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the ArraySegment being searched</param>
/// <param name="target">the ArraySegment being searched for</param>
/// <returns></returns>
public static int IndexOf<T>(ArraySegment<T> source, ArraySegment<T> target) where T : struct
{
return IndexOf(source.Array, source.Offset, source.Count, target.Array, target.Offset, target.Count);
}
/// <summary>
/// Code shared by array to do searches.
/// The source is the array being searched, and the target is the array being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the array being searched</param>
/// <param name="sourceOffset">offset of the source array</param>
/// <param name="sourceCount">count of the source array</param>
/// <param name="target">the array being searched for</param>
/// <param name="targetOffset">offset of the target array</param>
/// <param name="targetCount">count of the target array</param>
/// <returns></returns>
public static int IndexOf<T>(
T[] source, int sourceOffset, int sourceCount,
T[] target, int targetOffset, int targetCount) where T : struct
{
return IndexOf(source, sourceOffset, sourceCount, target, targetOffset, targetCount, 0);
}
/// <summary>
/// Code shared by array to do searches.
/// The source is the array being searched, and the target is the array being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the array being searched</param>
/// <param name="sourceOffset">offset of the source array</param>
/// <param name="sourceCount">count of the source array</param>
/// <param name="target">the array being searched for</param>
/// <param name="targetOffset">offset of the target array</param>
/// <param name="targetCount">count of the target array</param>
/// <param name="fromIndex">the index to begin searching from</param>
/// <returns></returns>
internal static int IndexOf<T>(
T[] source, int sourceOffset, int sourceCount,
T[] target, int targetOffset, int targetCount, int fromIndex) where T : struct
{
if (fromIndex >= sourceCount)
{
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0)
{
fromIndex = 0;
}
if (targetCount == 0)
{
return fromIndex;
}
T first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++)
{
if (!Equals(source[i], first))
{
while (++i <= max && !Equals(source[i], first)) ;
}
if (i <= max)
{
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && Equals(source[j], target[k]); j++, k++) ;
if (j == end)
{
return i - sourceOffset;
}
}
}
return -1;
}
/// <summary>
/// Code shared by ArraySegment to do searches.
/// The source is the ArraySegment being searched, and the target is the ArraySegment being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the ArraySegment being searched</param>
/// <param name="target">the ArraySegment being searched for</param>
/// <returns></returns>
public static int LastIndexOf<T>(ArraySegment<T> source, ArraySegment<T> target) where T : struct
{
return LastIndexOf(source.Array, source.Offset, source.Count, target.Array, target.Offset, target.Count);
}
/// <summary>
/// Code shared by array to do searches.
/// The source is the array being searched, and the target is the array being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the array being searched</param>
/// <param name="sourceOffset">offset of the source array</param>
/// <param name="sourceCount">count of the source array</param>
/// <param name="target">the array being searched for</param>
/// <param name="targetOffset">offset of the target array</param>
/// <param name="targetCount">count of the target array</param>
/// <returns></returns>
public static int LastIndexOf<T>(
T[] source, int sourceOffset, int sourceCount,
T[] target, int targetOffset, int targetCount) where T : struct
{
return LastIndexOf(source, sourceOffset, sourceCount, target, targetOffset, targetCount, sourceOffset + sourceCount);
}
/// <summary>
/// Code shared by array to do searches.
/// The source is the array being searched, and the target is the array being searched for.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">the array being searched</param>
/// <param name="sourceOffset">offset of the source array</param>
/// <param name="sourceCount">count of the source array</param>
/// <param name="target">the array being searched for</param>
/// <param name="targetOffset">offset of the target array</param>
/// <param name="targetCount">count of the target array</param>
/// <param name="fromIndex">the index to begin searching from</param>
/// <returns></returns>
internal static int LastIndexOf<T>(
T[] source, int sourceOffset, int sourceCount,
T[] target, int targetOffset, int targetCount, int fromIndex) where T : struct
{
int rightIndex = sourceCount - targetCount;
if (fromIndex < 0)
{
return -1;
}
if (fromIndex > rightIndex)
{
fromIndex = rightIndex;
}
if (targetCount == 0)
{
return fromIndex;
}
int arrLastIndex = targetOffset + targetCount - 1;
T arrLastItem = target[arrLastIndex];
int min = sourceOffset + targetCount - 1;
int i = min + fromIndex;
startSearchForLastItem:
while (true)
{
while (i >= min && !Equals(source[i], arrLastItem))
{
i--;
}
if (i < min)
{
return -1;
}
int j = i - 1;
int start = j - (targetCount - 1);
int k = arrLastIndex - 1;
while (j > start)
{
if (!Equals(source[j--], target[k--]))
{
i--;
goto startSearchForLastItem;
}
}
return start - sourceOffset + 1;
}
}
}