dla podejścia funkcjonalnego, wy można wdrożyć wyliczający uprzedzoną tak:
IEnumerable<Item> collection = ...;
var lookahead = collection.Zip(collection.Skip(1), Tuple.Create);
moduł wyliczający będzie iterację krotek każdej pozycji i jest następujący element. Nie obejmuje to ostatniego elementu w kolekcji. To tylko kwestia wykonania zapytania.
var query = collection.Zip(collection.Skip(1), Tuple.Create)
.Where(tuple => tuple.Item1.Kind == null && tuple.Item2.Kind == null)
.Select(tuple => tuple.Item1);
Niestety będzie to bardzo nieefektywne. Wymieniasz długość kolekcji dwukrotnie i może to być bardzo kosztowne.
Lepiej byłoby napisać własny moduł wyliczający dla tego więc tylko przejść przez gromadzenie w jednym przebiegu:
public static IEnumerable<TResult> LookAhead<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TSource, TResult> selector)
{
if (source == null) throw new ArugmentNullException("source");
if (selector == null) throw new ArugmentNullException("selector");
using (var enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext())
{
//empty
yield break;
}
var current = enumerator.Current;
while (enumerator.MoveNext())
{
var next = enumerator.Current;
yield return selector(current, next);
current = next;
}
}
}
Wtedy zapytania staje:
var query = collection.LookAhead(Tuple.Create)
.Where(tuple => tuple.Item1.Kind == null && tuple.Item2.Kind == null)
.Select(tuple => tuple.Item1);
widzę indeks OUT w twoim rozwiązaniu wyjątek zakresu: jeśli ostatnią pozycją "Rodzaju" jest 'null', wówczas' list [i + 1] 'spowoduje nadindeksowanie listy. – nemesv
Edytowane: Dobra rozmowa. – Ocelot20
Nadal nie jest doskonały: zamień 'i' na' i + 1' w 'ElementAtOrDefault' oraz' ElementAt', aby był poprawny. – nemesv