Given a sequence of items as follows:
[ ("a", 1); ("a", 2); ("a", 3); ("b", 1); ("c", 2); ("c", 3) ]
How can I convert this lazily into:
{ ("a", { 1; 2; 3}); ("b", { 1 }); ("c", { 2; 3}) }
You can assume that the input data source is already sorted on the grouping key element e.g. "a" "b" and "c".
I'm using the { } there to indicate that it's a lazily-evaluated sequence of items.
I've gotten it working imperatively with two while loops operating over the IEnumerator of the source sequence, but this involves creating reference variables and mutation etc. etc. I'm sure that there are better ways of doing this, perhaps with Recursion or using some of the operations in the Seq library e.g. scan or unfold?
Will do the trick
If you want to implement this over
IEnumerable<'T>
(to make it lazy), then it is necessarily going to be somewhat imperative, because theIEnumerator<'T>
type that is used to iterate over the input is imperative. But the rest can be written as a recursive function using sequence expressions.The following is lazy in the first level (it produces each group lazily), but it does not produce elements of the group lazily (I think that would have pretty subtle semantics):
Unfortunately, this (pretty useful!) function is not included in the standard F# library, so if you want to group adjacent elements (rather than arbitrary elements in the list using
Seq.groupBy
), you have to define it yourself...In F#+ there is a generic function chunkBy that can be used to do that:
And it works with
seq
,array
andlist
.The implementation for
seq
is pretty much the same as thegroupdAdjacent
from Tomas.