From 695e0838c589f774bb1060c7b89597dce7f8e7b9 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Sat, 12 Oct 2024 15:54:18 +0200 Subject: [PATCH] std: Add 'iter::window' --- src/Std/Iteration.cs | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/Std/Iteration.cs b/src/Std/Iteration.cs index c2ce270..0ad1485 100644 --- a/src/Std/Iteration.cs +++ b/src/Std/Iteration.cs @@ -43,7 +43,7 @@ public static RuntimeBoolean Any(IEnumerable items) public static RuntimeBoolean AnyOf(IEnumerable items, Func closure) => RuntimeBoolean.From(items.Any(x => closure(x).As().IsTrue)); - /// A new list with the given item append to the given Iterable. + /// A generator for the given item append to the given Iterable. [ElkFunction("append")] public static RuntimeGenerator Append(IEnumerable items, RuntimeObject item) => new(items.Append(item)); @@ -86,7 +86,7 @@ public static RuntimeList Collect(IEnumerable items) /// The first Iterable. /// The second Iterable. - /// A new list containing the items of both the the given Iterables. + /// A generator for the items of both the the given Iterables. [ElkFunction("concat")] public static RuntimeGenerator Concat(IEnumerable first, IEnumerable second) => new(first.Concat(second)); @@ -426,7 +426,7 @@ private static IEnumerable GetCartesianProduct(IEnumerableA new list with the given item prepended to the given Iterable. + /// A generator for the given item prepended to the given Iterable. [ElkFunction("prepend")] public static RuntimeGenerator Prepend(IEnumerable items, RuntimeObject item) => new(items.Prepend(item)); @@ -570,7 +570,7 @@ public static RuntimeGenerator Reverse(IEnumerable items) /// All items /// The amount of items to skip from the left - /// A new list without the first n items. + /// A generator for the first n items. [ElkFunction("skip")] public static RuntimeGenerator Skip(IEnumerable items, RuntimeInteger count) => new(items.Skip((int)count.Value).ToList()); @@ -600,21 +600,20 @@ public static RuntimeRange StepBy(RuntimeRange range, RuntimeInteger step) /// All items /// The amount of items to take from the left - /// A new list with the specified amount of items. + /// A generator for the specified amount of items. [ElkFunction("take")] public static RuntimeGenerator Take(IEnumerable items, RuntimeInteger count) => new(items.Take((int)count.Value).ToList()); /// All items /// - /// [ElkFunction("takeWhile")] public static RuntimeGenerator TakeWhile(IEnumerable items, Func closure) => new(items.TakeWhile(x => closure(x).As().IsTrue).ToList()); /// The first Iterable /// The second Iterable - /// A new list with the items from the given Iterables combined, excluding duplicates. + /// A generator for the items from the given Iterables combined, excluding duplicates. [ElkFunction("union")] public static RuntimeGenerator Union(IEnumerable first, IEnumerable second) => new(first.Union(second)); @@ -623,13 +622,46 @@ public static RuntimeGenerator Union(IEnumerable first, IEnumerab /// The second Iterable /// /// - /// A new list with the items from the given Iterables combined, excluding duplicates. + /// A generator for the items from the given Iterables combined, excluding duplicates. /// The closure selects the key of each item. /// [ElkFunction("unionBy")] public static RuntimeGenerator UnionBy(IEnumerable first, IEnumerable second, Func closure) => new(first.UnionBy(second, closure)); + /// The values to slide over + /// The size of the window + /// A generator for a sliding window over the given values. + /// + /// [1, 2, 3, 4, 5] | iter::window(2) #=> [[1, 2], [2, 3], [3, 4], [4, 5], [5, nil]] + /// + [ElkFunction("window")] + public static RuntimeGenerator Window(IEnumerable values, RuntimeInteger size) + => new(Window(values, size.Value)); + + private static IEnumerable Window(IEnumerable values, long size) + { + var buffer = new Queue(); + foreach (var value in values) + { + buffer.Enqueue(value); + if (buffer.Count == size) + { + yield return new RuntimeList(buffer.ToList()); + buffer.Dequeue(); + } + } + + if (buffer.Any()) + { + while (buffer.Count < size) + buffer.Enqueue(RuntimeNil.Value); + + yield return new RuntimeList(buffer.ToList()); + buffer.Clear(); + } + } + /// /// /// A list containing a tuple for each item in the original container.