複数の連続する値のリストを検索する方法はありますか? Find と IndexOf を見てきましたが、Find は現在の値のみを使用する Predicates を使用し、IndexOf はバイト パラメーターのみを使用します。
独自のソリューションをコーディングすることはできますが、この一般的な問題に対するソリューションがまだ利用できないことを確認したいと考えています。
前もって感謝します。
正直なところ、特に一般的な問題ではないと思います。フレームワークには何もないと確信しています。
独自の実装を効率化するか単純化するかを検討する必要があると思います。かなり単純な拡張メソッドのバージョンは次のようになります。
public static int IndexOf<T>(this IEnumerable<T> source,
T first,
T second)
{
IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
// We can only return when we've read source[index+1], so we need
// to keep one value behind
int index=-1;
T prev = default(T);
foreach (T element in source)
{
if (comparer.Equals(first, prev) &&
comparer.Equals(second, element) &&
index >= 0) // Avoid edge cases where first=default(T)
{
return index;
}
index++;
prev = element;
}
return -1;
}
リストを連続する値のグループに分割し、それぞれの内容を比較することも考えられます。分割を実行する別の関数 (F# コア ライブラリから取得) を次に示します。
static IEnumerable<T[]> Windowed<T>(this IEnumerable<T> source, int size)
{
if (source == null)
throw new NullReferenceException();
if (size <= 0)
throw new ArgumentOutOfRangeException("size", "The window size must be positive.");
var arr = new T[size];
var r = size-1;
var i = 0;
foreach (T item in source)
{
arr[i] = item;
i = (i+1) % size;
if (r == 0)
{
var res = new T[size];
for (int j = 0; j < size; j++)
res[j] = arr[(i+j) % size];
yield return res;
}
else
r -= 1;
}
}
上記の関数を次のように使用できます。
var result = Enumerable.Range(1, 10).Windowed(2)
.Where(a => a[0] == 3 && a[1] == 4)
.First();
これは、質問に対する私自身の解決策です。このメソッドは、任意の量のアイテムを処理でき、O(n) であり、非常にシンプルであるため、気に入っています。
<Extension()> Public Function Find(Of T)(ByVal list As List(Of T), ByVal searchedValue As T(), ByVal startingIndex As Integer) As Integer
Dim mainIndex As Integer
Dim searchedIndex As Integer
Dim result As Integer
result = -1 ' Initialize result
mainIndex = startingIndex
While mainIndex < list.Count AndAlso result = -1
If list(mainIndex).Equals(searchedValue(0)) Then
searchedIndex = 0
While searchedIndex < searchedValue.Length AndAlso (list(mainIndex + searchedIndex).Equals(searchedValue(searchedIndex)))
searchedIndex = searchedIndex + 1
End While
If searchedIndex = searchedValue.Length AndAlso list(mainIndex + searchedIndex - 1).Equals(searchedValue(searchedIndex - 1)) Then
result = mainIndex
End If
End If
mainIndex = mainIndex + 1
End While
Return result
End Function