-
Notifications
You must be signed in to change notification settings - Fork 418
Open
Labels
Description
I'd like to propose a new operator that splits a sequence in two at a given index. The first sequence will contain all the items that appear before the index in the source sequence and the second will contain those items that appear at and after the index. A negative index would be allowed and would have the equivalent behavior of specifying an index of 0.
The follow table illustrates the splits that SplitAt
will produce for a sample of indexes on a given source:
Source | Index | Split 1 | Split 2 |
---|---|---|---|
[1,2,3,4,5,6,7,8,9,10] | 0 | [] | [1,2,3,4,5,6,7,8,9,10] |
[1,2,3,4,5,6,7,8,9,10] | 2 | [1,2] | [3,4,5,6,7,8,9,10] |
[1,2,3,4,5,6,7,8,9,10] | 5 | [1,2,3,4,5] | [6,7,8,9,10] |
[1,2,3,4,5,6,7,8,9,10] | 10 | [1,2,3,4,5,6,7,8,9,10] | [] |
[1,2,3,4,5,6,7,8,9,10] | 20 | [1,2,3,4,5,6,7,8,9,10] | [] |
[1,2,3,4,5,6,7,8,9,10] | -5 | [] | [1,2,3,4,5,6,7,8,9,10] |
Prototype
public static TResult SplitAt<T, TResult>(
this IEnumerable<T> source, int index,
Func<IEnumerable<T>, IEnumerable<T>, TResult> resultSelector) =>
source.Index()
.Partition(e => e.Key < index,
(xs, ys) => resultSelector(from x in xs select x.Value,
from y in ys select y.Value));
Example
var xs = Enumerable.Range(1, 10);
var results =
from i in new[] { 0, 2, 5, 10, 20, -5 }
select xs.SplitAt(i, (h, t) => new
{
Index = i,
Head = "[" + string.Join(",", h) + "]",
Tail = "[" + string.Join(",", t) + "]",
});
foreach (var result in results)
Console.WriteLine(result);
Output
{ Index = 0, Head = [], Tail = [1,2,3,4,5,6,7,8,9,10] }
{ Index = 2, Head = [1,2], Tail = [3,4,5,6,7,8,9,10] }
{ Index = 5, Head = [1,2,3,4,5], Tail = [6,7,8,9,10] }
{ Index = 10, Head = [1,2,3,4,5,6,7,8,9,10], Tail = [] }
{ Index = 20, Head = [1,2,3,4,5,6,7,8,9,10], Tail = [] }
{ Index = -5, Head = [], Tail = [1,2,3,4,5,6,7,8,9,10] }
TAGC and Athari