From c98576b18cf55a5b0e4f5a7728c31fce37b5c79f Mon Sep 17 00:00:00 2001 From: Stuart Turner Date: Sun, 22 Jan 2023 18:13:18 -0600 Subject: [PATCH] Improve performance of `ScanRight` --- Source/SuperLinq.Async/ScanRight.cs | 20 +++++++++++--------- Source/SuperLinq/ScanRight.cs | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Source/SuperLinq.Async/ScanRight.cs b/Source/SuperLinq.Async/ScanRight.cs index e5e509da..f1fabbeb 100644 --- a/Source/SuperLinq.Async/ScanRight.cs +++ b/Source/SuperLinq.Async/ScanRight.cs @@ -93,18 +93,18 @@ public static IAsyncEnumerable ScanRight(this IAsyncEnumerable static async IAsyncEnumerable _(IAsyncEnumerable source, Func> func, [EnumeratorCancellation] CancellationToken cancellationToken = default) { - await using var e = source.Reverse().GetConfiguredAsyncEnumerator(cancellationToken); + var list = await source.ToListAsync(cancellationToken).ConfigureAwait(false); - if (!await e.MoveNextAsync()) + if (list.Count == 0) yield break; - var seed = e.Current; - var stack = new Stack(); + var seed = list[^1]; + var stack = new Stack(list.Count); stack.Push(seed); - while (await e.MoveNextAsync()) + for (var i = list.Count - 2; i >= 0; i--) { - seed = await func(e.Current, seed, cancellationToken).ConfigureAwait(false); + seed = await func(list[i], seed, cancellationToken).ConfigureAwait(false); stack.Push(seed); } @@ -207,12 +207,14 @@ public static IAsyncEnumerable ScanRight(this static async IAsyncEnumerable _(IAsyncEnumerable source, TAccumulate seed, Func> func, [EnumeratorCancellation] CancellationToken cancellationToken = default) { - var stack = new Stack(); + var list = await source.ToListAsync(cancellationToken).ConfigureAwait(false); + + var stack = new Stack(list.Count + 1); stack.Push(seed); - await foreach (var i in source.Reverse().WithCancellation(cancellationToken).ConfigureAwait(false)) + for (var i = list.Count - 1; i >= 0; i--) { - seed = await func(i, seed, cancellationToken).ConfigureAwait(false); + seed = await func(list[i], seed, cancellationToken).ConfigureAwait(false); stack.Push(seed); } diff --git a/Source/SuperLinq/ScanRight.cs b/Source/SuperLinq/ScanRight.cs index 3c3c7f46..c57fb0db 100644 --- a/Source/SuperLinq/ScanRight.cs +++ b/Source/SuperLinq/ScanRight.cs @@ -17,7 +17,7 @@ public static partial class SuperEnumerable /// is . /// is . /// - /// i.ToString()).ScanRight((a, b) => $"({a}+{b})"); /// ]]> /// The result variable will contain [ "(1+(2+(3+(4+5))))", "(2+(3+(4+5)))", "(3+(4+5))", "(4+5)", "5" ]. @@ -36,18 +36,18 @@ public static IEnumerable ScanRight(this IEnumerable static IEnumerable _(IEnumerable source, Func func) { - using var e = source.Reverse().GetEnumerator(); + var list = source is IList l ? l : source.ToList(); - if (!e.MoveNext()) + if (list.Count == 0) yield break; - var seed = e.Current; - var stack = new Stack(); + var seed = list[^1]; + var stack = new Stack(list.Count); stack.Push(seed); - while (e.MoveNext()) + for (var i = list.Count - 2; i >= 0; i--) { - seed = func(e.Current, seed); + seed = func(list[i], seed); stack.Push(seed); } @@ -91,12 +91,13 @@ public static IEnumerable ScanRight(this IEnu static IEnumerable _(IEnumerable source, TAccumulate seed, Func func) { - var stack = new Stack(); + var list = source is IList l ? l : source.ToList(); + var stack = new Stack(list.Count + 1); stack.Push(seed); - foreach (var i in source.Reverse()) + for (var i = list.Count - 1; i >= 0; i--) { - seed = func(i, seed); + seed = func(list[i], seed); stack.Push(seed); }