Đối với một cách tiếp cận chức năng, bạn có thể thực hiện một điều tra viên lookahead như vậy:
IEnumerable<Item> collection = ...;
var lookahead = collection.Zip(collection.Skip(1), Tuple.Create);
Điều tra viên sẽ lặp qua bộ dữ liệu của mỗi mục và mục sau đây. Điều này loại trừ mục cuối cùng trong bộ sưu tập. Sau đó, nó chỉ là vấn đề thực hiện truy vấn.
var query = collection.Zip(collection.Skip(1), Tuple.Create)
.Where(tuple => tuple.Item1.Kind == null && tuple.Item2.Kind == null)
.Select(tuple => tuple.Item1);
Thật không may điều này sẽ rất kém hiệu quả. Bạn đang liệt kê chiều dài của bộ sưu tập hai lần và có thể rất tốn kém.
Sẽ tốt hơn để viết Enumerator của riêng bạn cho điều này, do đó bạn chỉ đi qua các bộ sưu tập trong một pass:
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;
}
}
}
Sau đó truy vấn trở thành:
var query = collection.LookAhead(Tuple.Create)
.Where(tuple => tuple.Item1.Kind == null && tuple.Item2.Kind == null)
.Select(tuple => tuple.Item1);
Nguồn
2012-07-01 00:52:49
tôi thấy một chỉ số ra khỏi phạm vi ngoại lệ trong giải pháp của bạn: nếu mục cuối cùng 'Loại' là' null' thì 'danh sách [i + 1]' sẽ ghi đè lên danh sách. – nemesv
Đã chỉnh sửa: Cuộc gọi tốt. – Ocelot20
Vẫn không hoàn hảo: thay thế 'i' bằng' i + 1' trong 'ElementAtOrDefault' và' ElementAt' để làm cho nó đúng. – nemesv