-
-
Notifications
You must be signed in to change notification settings - Fork 444
Open
Description
More of a convenience instead of rolling my own extension, it'd be nice to have a declarative TakeUntil in addition to TakeWhile that includes every element up to and including the element that fails the predicate. Imagine something like this:
public static string TransformLine(string line)
{
return line;
}
public static IEnumerable<string> TransformLines(this IEnumerable<string> lines)
{
foreach (var line in lines)
{
if(!SomeConditionIsMet(line))
{
yield return "MyString";
yield break;
}
yield return TransformLine(line);
}
}If I want to do something like this using Seq using a more composable and declarative approach, I'd need to do something like:
public static Seq<string> TransformLines(this Seq<string> lines)
=> pipe(
lines.TakeWhile(SomeConditionIsMet).Map(TransformLine),
seq => lines.Exists(line => !SomeConditionIsMet(line)) ? seq.Add("MyString") : seq
);whereas, if there's a TakeUntil, you can absorb the funky logic and just do:
public static string TransformLine(string line)
{
return SomeConditionIsMet(line) ? line : "MyString";
}
public static Seq<string> TransformLines(this Seq<string> lines)
=> lines.TakeUntil(SomeConditionIsMet).Map(TransformLine);A naïve implementation would be something like
/// <summary>
/// Iterate the sequence, yielding items until one is encountered
/// that does not match the predicate provided.
/// </summary>
/// <returns>
/// A new sequence with the first items that match the
/// predicate and the first element that did not match the predicate.
/// </returns>
[Pure]
public Seq<A> TakeUntil(Func<A, bool> pred)
{
return new Seq<A>(new SeqLazy<A>(Yield(Value, pred)));
static IEnumerable<A> Yield(IEnumerable<A> xs, Func<A, bool> f)
{
foreach (var x in xs)
{
if (!f(x))
{
yield return x;
yield break;
}
yield return x;
}
}
}To me, this is conceptually equivalent in terms of how to
TakeWhile() => for(int i = 0; i < bound; i++)
TakeUntil() => for(int i = 0; i <= bound; i++)
Metadata
Metadata
Assignees
Labels
No labels