Skip to content

Commit

Permalink
Improve performance of ScanRight
Browse files Browse the repository at this point in the history
  • Loading branch information
viceroypenguin committed Jan 23, 2023
1 parent 75b3808 commit c98576b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 19 deletions.
20 changes: 11 additions & 9 deletions Source/SuperLinq.Async/ScanRight.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,18 @@ public static IAsyncEnumerable<TSource> ScanRight<TSource>(this IAsyncEnumerable

static async IAsyncEnumerable<TSource> _(IAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, ValueTask<TSource>> 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<TSource>();
var seed = list[^1];
var stack = new Stack<TSource>(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);
}

Expand Down Expand Up @@ -207,12 +207,14 @@ public static IAsyncEnumerable<TAccumulate> ScanRight<TSource, TAccumulate>(this

static async IAsyncEnumerable<TAccumulate> _(IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TSource, TAccumulate, CancellationToken, ValueTask<TAccumulate>> func, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var stack = new Stack<TAccumulate>();
var list = await source.ToListAsync(cancellationToken).ConfigureAwait(false);

var stack = new Stack<TAccumulate>(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);
}

Expand Down
21 changes: 11 additions & 10 deletions Source/SuperLinq/ScanRight.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static partial class SuperEnumerable
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="func"/> is <see langword="null"/>.</exception>
/// <example>
/// <code><![CDATA[
/// <code><![CDATA[
/// var result = Enumerable.Range(1, 5).Select(i => i.ToString()).ScanRight((a, b) => $"({a}+{b})");
/// ]]></code>
/// The <c>result</c> variable will contain <c>[ "(1+(2+(3+(4+5))))", "(2+(3+(4+5)))", "(3+(4+5))", "(4+5)", "5" ]</c>.
Expand All @@ -36,18 +36,18 @@ public static IEnumerable<TSource> ScanRight<TSource>(this IEnumerable<TSource>

static IEnumerable<TSource> _(IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
{
using var e = source.Reverse().GetEnumerator();
var list = source is IList<TSource> l ? l : source.ToList();

if (!e.MoveNext())
if (list.Count == 0)
yield break;

var seed = e.Current;
var stack = new Stack<TSource>();
var seed = list[^1];
var stack = new Stack<TSource>(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);
}

Expand Down Expand Up @@ -91,12 +91,13 @@ public static IEnumerable<TAccumulate> ScanRight<TSource, TAccumulate>(this IEnu

static IEnumerable<TAccumulate> _(IEnumerable<TSource> source, TAccumulate seed, Func<TSource, TAccumulate, TAccumulate> func)
{
var stack = new Stack<TAccumulate>();
var list = source is IList<TSource> l ? l : source.ToList();
var stack = new Stack<TAccumulate>(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);
}

Expand Down

0 comments on commit c98576b

Please sign in to comment.