Is there any way I can separate a List<SomeObject>
into several separate lists of SomeObject
, using the item index as the delimiter of each split?
Let me exemplify:
I have a List<SomeObject>
and I need a List<List<SomeObject>>
or List<SomeObject>[]
, so that each of these resulting lists will contain a group of 3 items of the original list (sequentially).
eg.:
Original List:
[a, g, e, w, p, s, q, f, x, y, i, m, c]
Resulting lists:
[a, g, e], [w, p, s], [q, f, x], [y, i, m], [c]
I'd also need the resulting lists size to be a parameter of this function.
Using modular partitioning:
In general the approach suggested by CaseyB works fine, in fact if you are passing in a
List<T>
it is hard to fault it, perhaps I would change it to:Which will avoid massive call chains. Nonetheless, this approach has a general flaw. It materializes two enumerations per chunk, to highlight the issue try running:
To overcome this we can try Cameron's approach, which passes the above test in flying colors as it only walks the enumeration once.
Trouble is that it has a different flaw, it materializes every item in each chunk, the trouble with that approach is that you run high on memory.
To illustrate that try running:
Finally, any implementation should be able to handle out of order iteration of chunks, for example:
Many highly optimal solutions like my first revision of this answer failed there. The same issue can be seen in casperOne's optimized answer.
To address all these issues you can use the following:
There is also a round of optimisations you could introduce for out-of-order iteration of chunks, which is out of scope here.
As to which method you should choose? It totally depends on the problem you are trying to solve. If you are not concerned with the first flaw the simple answer is incredibly appealing.
Note as with most methods, this is not safe for multi threading, stuff can get weird if you wish to make it thread safe you would need to amend
EnumeratorWrapper
.Can work with infinite generators:
Demo code: https://ideone.com/GKmL7M
But actually I would prefer to write corresponding method without linq.
Old code, but this is what I've been using:
So performatic as the Sam Saffron's approach.
}
It's an old solution but I had a different approach. I use
Skip
to move to desired offset andTake
to extract desired number of elements: