Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LINQ SelectAggregate #26945

Closed
Thaina opened this issue Jul 25, 2018 · 8 comments
Closed

LINQ SelectAggregate #26945

Thaina opened this issue Jul 25, 2018 · 8 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Linq
Milestone

Comments

@Thaina
Copy link

Thaina commented Jul 25, 2018

I wish we could have select that could also keep state of aggregation and continue the iteration, send the aggregation to the next select

It should be simple to add this

public static IEnumerable<V> SelectAggregate<T,V>(this IEnumerable<T> items,V seed,Func<V,T,V> func)
{
	foreach(var item in items)
	{
		seed	= func(seed,item);
		yield return seed;
	}
}

////

var array = new int[]{ 1,2,3 };
var sumArray = array.SelectAggregate(0,(seed,item) => seed + item).ToArray();
// { 1,3,6 }
@Clockwork-Muse
Copy link
Contributor

nit: Select is the equivalent to map in a number of other languages/libraries, where each transformation is supposed to be independent of each other. Perhaps a better name would be RunningAggregate

Note that, at least in database land, running aggregates are normally part of windowing functions.

Parallelization (in PLINQ) would be a pain, but likely possible.

@svick
Copy link
Contributor

svick commented Jul 25, 2018

Note that F# already has a very similar function: Seq.scan. In F#, the code above would look like this:

let array = [| 1; 2; 3 |]
let sumArray = array |> Seq.scan (fun seed item -> seed + item) 0 |> Seq.toArray

Though there seems to be one difference between Seq.scan and the proposed SelectAggregate: Seq.scan returns the initial seed as the first item in the result. So, sumArray above would actually be 0, 1, 3, 6.

@Thaina
Copy link
Author

Thaina commented Aug 2, 2018

It could be the same. I just think the seed is something we put it directly so we know about it beforehand. It could be prepend directly so it not necessary

But it's fine to have consistency with F#. I just think it convenient

@quinmars
Copy link

There is also System.Linq.EnumerableEx.Scan(...) of the System.Interactive package.

@RyotaMurohoshi
Copy link

Nice suggestion! I want to use it!!!

But, how about rename the suggesting method to Scan?

MoreLinq that is LINQ extension library has Scan method. The method is same you suggested.

MoreLinq Scan

Haskell and Scala have scan methods that have same feature too.

And many Rx frameworks have Scan operator that similar to suggested method.

I think that Scan is good for Rx users and Functional language users.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@adamsitnik adamsitnik removed the untriaged New issue has not been triaged by the area owner label Sep 2, 2020
@eiriktsarpalis
Copy link
Member

In the interest of keeping the Linq API surface small, we would need to assess the popularity of such an addition before we commit to it. My impression is that fold/scan-like constructs are kind of niche in the context of an imperative language. c.f. #20330

@Thaina
Copy link
Author

Thaina commented Sep 9, 2021

@eiriktsarpalis I don't think scan is actually niche. But people don't actually know its usage and then just fall back to normal for loop (arguably most linq in general face this same problem). While actually it could all be rewritten into linq language

Another issue is scan can be imitate by create cache variable outside of linq chain. But in turn its destroy immutibility and scope of variable. This actually is the usage of scan but people just workaround it carelessly

Another usage of scan is using in conjunction with TakeWhile. Such as summing the element but cap limit before its reach some value. This work with any cumulative logic

@eiriktsarpalis
Copy link
Member

But people don't actually know its usage and then just fall back to normal for loop (arguably most linq in general face this same problem).

I mean that sounds fine to me. Alternatively folks that need such a pattern can easily either write their own extension method or use one of the many third-party libraries that provide LINQ extensions.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Linq
Projects
None yet
Development

No branches or pull requests

9 participants