Skip to content

SplitAt (split a sequence in two at a specified index) #315

@atifaziz

Description

@atifaziz

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] }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions