这是this answer 的通用实现,它允许任何IList,并且可以传入可选的IEqualityComparer。这不是最快的搜索方式,但它是进行更高级答案的良好起点。
static class GenericSearcher
{
static readonly int[] Empty = new int[0];
public static int[] Locate<T>(this IList<T> self, IList<T> candidate)
{
return Locate(self, candidate, EqualityComparer<T>.Default);
}
public static int[] Locate<T>(this IList<T> self, IList<T> candidate, IEqualityComparer<T> comparer)
{
if (IsEmptyLocate(self, candidate))
return Empty;
var list = new List<int>();
for (int i = 0; i < self.Count; i++)
{
if (!IsMatch(self, i, candidate, comparer))
continue;
list.Add(i);
}
return list.Count == 0 ? Empty : list.ToArray();
}
static bool IsMatch<T>(IList<T> array, int position, IList<T> candidate, IEqualityComparer<T> comparer)
{
if (candidate.Count > (array.Count - position))
return false;
for (int i = 0; i < candidate.Count; i++)
if (comparer.Equals(array[position + i],candidate[i]) == false)
return false;
return true;
}
static bool IsEmptyLocate<T>(ICollection<T> array, ICollection<T> candidate)
{
return array == null
|| candidate == null
|| array.Count == 0
|| candidate.Count == 0
|| candidate.Count > array.Count;
}
}
已使用 VB 代码更新(感谢 ajakblackgoat):
Module GenericSearcher
Private ReadOnly Empty As Integer() = New Integer(-1) {}
<System.Runtime.CompilerServices.Extension> _
Public Function Locate(Of T)(self As IList(Of T), candidate As IList(Of T)) As Integer()
Return Locate(self, candidate, EqualityComparer(Of T).[Default])
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function Locate(Of T)(self As IList(Of T), candidate As IList(Of T), comparer As IEqualityComparer(Of T)) As Integer()
If IsEmptyLocate(self, candidate) Then
Return Empty
End If
Dim list = New List(Of Integer)()
For i As Integer = 0 To self.Count - 1
If Not IsMatch(self, i, candidate, comparer) Then
Continue For
End If
list.Add(i)
Next
Return If(list.Count = 0, Empty, list.ToArray())
End Function
Private Function IsMatch(Of T)(array As IList(Of T), position As Integer, candidate As IList(Of T), comparer As IEqualityComparer(Of T)) As Boolean
If candidate.Count > (array.Count - position) Then
Return False
End If
For i As Integer = 0 To candidate.Count - 1
If Not comparer.Equals(array(position + i), candidate(i)) Then
Return False
End If
Next
Return True
End Function
Private Function IsEmptyLocate(Of T)(array As ICollection(Of T), candidate As ICollection(Of T)) As Boolean
Return array Is Nothing OrElse candidate Is Nothing OrElse array.Count = 0 OrElse candidate.Count = 0 OrElse candidate.Count > array.Count
End Function
End Module