【.NET / C#】SubarrayUtils(查找子数组工具类)

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;
        }
    }

}
posted @ 2019-06-13 11:21  XKIND  阅读(178)  评论(0编辑  收藏  举报