8000 Scan by key/group · Issue #563 · morelinq/MoreLINQ · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Scan by key/group #563
Closed
Closed
@atifaziz

Description

@atifaziz

I would like to suggest adding ScanBy. The idea has floated out of review of PR #562 that proposes to add IndexBy (see also #560) but where ScanBy would be an even more general implementation.

Prototype

public static IEnumerable<TResult>
    ScanBy<T, TKey, TState, TResult>(
        this IEnumerable<T> source,
        Func<T, TKey> keySelector,
        Func<TKey, TState> seedSelector,
        Func<T, TKey, TState, TState> accumulator,
        Func<T, TKey, TState, TResult> resultSelector,
        IEqualityComparer<TKey> comparer = null)
{
    var stateByKey = new Dictionary<TKey, TState>(comparer); 
    foreach (var item in source)
    {
        var key = keySelector(item);
        if (!stateByKey.TryGetValue(key, out var state))
            state = seedSelector(key);
        state = accumulator(item, key, state);
        stateByKey[key] = state;
        yield return resultSelector(item, key, state);
    }
}

Example

As an example, here is IndexBy implemented in terms of ScanBy:

public static IEnumerable<TResult>
    IndexBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TSource, TKey, int, TResult> resultSelector,
        IEqualityComparer<TKey> comparer) =>
    source.ScanBy(keySelector, k => -1, (e, k, i) => i + 1, resultSelector, comparer);

Do we need such a function? Not really, because it could be implemented ad-hoc:

foreach (var (x, k, i) in 
    Enumerable.Range(0, 20)
              .Shuffle()
              .ScanBy(x => x / 5, k => -1, (x, k, i) => i + 1, ValueTuple.Create))
{
    // do something...
}

Here's a running max by key/group:

foreach (var (x, k, max) in 
    Enumerable.Range(0, 20)
              .Shuffle()
              .ScanBy(x => x / 5,
                      k => int.MinValue,
                      (x, k, m) => Math.Max(x, m),
                      ValueTuple.Create);
{
    // do something...
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0