❔ LINQ: Group and extract all consecutive elements from List that match predicate
Example:
Expected output:
Is there such functionality in LINQ?
32 Replies
Any suggestions for a performant implementation?
Just a for loop, right?
Or i guess if you need it to work on any ienumerable, a foreach one
Or a
foreach
, will work with any IEnumerable
I think I'd prefer a solution using LINQ expressions
Hm?
Uh
Unless a "manual" loop is unavoidable
Write your own, using a loop
I was thinking about using GroupBy and somehow combining the value with its index, then working with that
You mentioned performant
That will be awful
Yeah I suppose a manual foreach is the best then
Weird/Sad that there isnt a GroupConsecutive method :/
I adjusted my example to better reflect a general solution
Yeah having multiple KVP is not good, since they all contain the same Key
Would IGrouping be more appropiate?
Or maybe a KeyValuePair<T, IReadOnlyList<T>>
Yeah
Wait huh?
You want the values?
How does that make sense?
You already select the value in the call
Look at my example.
My supposed "GroupConsecutive" method will give you a List which itself contains Groupings of all the consecutive elements in the given List.
Essentially it (as the name implies) groups all the elements which are consecutively equal in the list.
So 1,2,3,4 would give you 4 groupings, but 1,2,2,3 would only give you 3, while 1,2,2,3,2 would give you 4 again
Hm
I suppose for simple integers it does not make a lot of sense
but I could also imagine needing a ConsecutiveGroupBy method, where the key is chosen from an object
Then the grouping would only have that key as the key of the grouping, but the actual elements could be objects
Uhh that doesnt compile for me
Wouldn't it be
<TValue, int>
Huh seems to be a weird bug with copy and paste...if I manually write the exact same thing out it works.
https://stackoverflow.com/questions/20469416/linq-to-find-series-of-consecutive-numbers
modify it for consecutive and equal
I'd have called this a folding problem
Presumably you don't actually want to group the values. You just want to see how many of each sequence there are
So why store anything more than the keys and counts?
So you'd use LINQ
Aggregate
with a result value that holds a list of tuples representing the key and the count. For each iteration you'd compare the current key with the most recent key in the result value. If the keys are different, push a new tuple onto the result with the new key and a count of zero
@TheHelpfulHelper try thisyeah but who would want to use that
that's incredibly unreadable
also what's with those
-1
s?It's because C# isn't bundled with a
maybe
type
And everybody knows that readability is subjective
The reason I like this solution is that it's performant and that any mistake you make will lead to a compiler error. I agree it should be pulled into its own declaration rather than as a big inline blob thoughno but, why
-1
?
does this not mess up if the first item in the enumerable is -1
?
does this even work with other types?
this is just not a solution, at all
and don't talk about this being performant, this is using linqHey @TheHelpfulHelper I cleaned up my first solution and made it generic for you
I hope this helps you
Testing it produces the answers you were hoping to see
you have like a billion nullability warnings there lol
Oh my mistake. Could you point some out, please?
you just need to put
T?
almost everywhere
because T
could technically be a reference type
where default(T)
would be null
Ah yes I'd accounted for nulls in the code but had forgotten to annotate the type
Well spotted
and for a
CountContiguousBy
, just do;
actually you wanna do the select beforehand and do the equality comparison on the result of that
so like this;
also here's the benchmark code;
It'd be nice if the OP showed up to appreciate how much work we're putting in for them lol
I would argue that we've just produced two valid solutions written using different paradigms, although I'd prefer yours if it was in a library.
You could speed mine up even more for ILists, i reckon
Use the indexer instead
but at that point it becomes a bit ridiculous i guess
I'd generally advocate using the smallest tool necessary for the job haha
Otherwise you end up with things like Spring Boot
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.