使用linq将以下内容应用于序列的最可读方式是什么?
TakeWhile elements are valid but always at least the first element编辑:我已经更新了标题,更准确。 我很抱歉有什么困惑,下面的答案肯定会教给我一些东西!
预期的行为是这样的:Take while元素有效。 如果结果是一个空序列,无论如何要采取第一个元素。
What would be the most readable way to apply the following to a sequence using linq:
TakeWhile elements are valid but always at least the first elementEDIT: I have updated the title, to be more precise. I'm sorry for any confusion, the answers below have definitely taught me something!
The expected behavior is this: Take while element are valid. If the result is an empty sequence, take the first element anyway.
最满意答案
据我所知,它可以最有效地手动实现,以确保它不会超过必要的枚举。
public static IEnumerable<TSource> TakeWhileOrFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { using (var enumerator = source.GetEnumerator()) { if (!enumerator.MoveNext()) yield break; TSource current = enumerator.Current; yield return current; if (predicate(current)) { while (enumerator.MoveNext() && predicate(current = enumerator.Current)) yield return current; } } }为了完成,包含索引的重载:
public static IEnumerable<TSource> TakeWhileOrFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) { using (var enumerator = source.GetEnumerator()) { if (!enumerator.MoveNext()) yield break; TSource current = enumerator.Current; int index = 0; yield return current; if (predicate(current, index++)) { while (enumerator.MoveNext() && predicate(current = enumerator.Current, index++)) yield return current; } } }It would be most efficiently implemented manually as far as I can tell to ensure that it isn't enumerated over more than necessary.
public static IEnumerable<TSource> TakeWhileOrFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { using (var enumerator = source.GetEnumerator()) { if (!enumerator.MoveNext()) yield break; TSource current = enumerator.Current; yield return current; if (predicate(current)) { while (enumerator.MoveNext() && predicate(current = enumerator.Current)) yield return current; } } }And for the sake of completion, an overload that includes the index:
public static IEnumerable<TSource> TakeWhileOrFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) { using (var enumerator = source.GetEnumerator()) { if (!enumerator.MoveNext()) yield break; TSource current = enumerator.Current; int index = 0; yield return current; if (predicate(current, index++)) { while (enumerator.MoveNext() && predicate(current = enumerator.Current, index++)) yield return current; } } }更多推荐
发布评论