Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move range #584

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
159 changes: 151 additions & 8 deletions Source/SuperLinq/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,30 @@ public static partial class SuperEnumerable
/// <remarks>
/// This operator uses deferred execution and streams its results.
/// </remarks>
public static IEnumerable<T> Move<T>(this IEnumerable<T> source, int fromIndex, int count, int toIndex)
public static IEnumerable<T> Move<T>(
this IEnumerable<T> source,
int fromIndex,
int count,
int toIndex
)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentOutOfRangeException.ThrowIfNegative(fromIndex);
ArgumentOutOfRangeException.ThrowIfNegative(count);
ArgumentOutOfRangeException.ThrowIfNegative(toIndex);

return
toIndex == fromIndex || count == 0
? source :
toIndex < fromIndex
? Core(source, toIndex, fromIndex - toIndex, count)
: Core(source, fromIndex, count, toIndex - fromIndex);
return toIndex == fromIndex || count == 0
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
? source
: toIndex < fromIndex
? Core(source, toIndex, fromIndex - toIndex, count)
: Core(source, fromIndex, count, toIndex - fromIndex);

static IEnumerable<T> Core(IEnumerable<T> source, int bufferStartIndex, int bufferSize, int bufferYieldIndex)
static IEnumerable<T> Core(
IEnumerable<T> source,
int bufferStartIndex,
int bufferSize,
int bufferYieldIndex
)
{
var hasMore = true;
bool MoveNext(IEnumerator<T> e) => hasMore && (hasMore = e.MoveNext());
Expand All @@ -72,4 +81,138 @@ static IEnumerable<T> Core(IEnumerable<T> source, int bufferStartIndex, int buff
yield return e.Current;
}
}

/// <summary>
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
/// Returns a sequence with a range of elements in the source sequence moved to a new offset.
/// </summary>
/// <typeparam name="T">
/// Type of the source sequence.
/// </typeparam>
/// <param name="source">
/// The source sequence.
/// </param>
/// <param name="range">
/// The range of values to move.
/// </param>
/// <param name="to">
/// The index where the specified range will be moved.</param>
/// <returns>
/// A sequence with the specified range moved to the new position.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="range"/>'s start is less than <c>0</c> or <paramref name="range"/>'s end is before start in the sequence.
/// </exception>
/// <remarks>
/// This operator uses deferred executing and streams its results.
/// </remarks>
public static IEnumerable<T> Move<T>(this IEnumerable<T> source, Range range, Index to)
{
if (range.Start.IsFromEnd || range.End.IsFromEnd || to.IsFromEnd)
{
int startIndex;
int endIndex;
int toIndex;

if (source.TryGetCollectionCount() is int count)
{
startIndex = range.Start.GetOffset(count);
endIndex = range.End.GetOffset(count);
toIndex = to.GetOffset(count);
yield return (T)Move(source, startIndex, endIndex - startIndex, toIndex);
}
else
{
switch ((range.Start.IsFromEnd, range.End.IsFromEnd, to.IsFromEnd))
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
{
case (false, false, true):
using (var e = source.GetEnumerator())
{
if (!e.MoveNext())
{
yield break;
}

var bufferCap = to.Value;
var moveCap = range.End.Value - range.Start.Value;
var buffer = new Queue<T>(bufferCap);
var move = new Queue<T>(moveCap);

buffer.Enqueue(e.Current);
count = 1;

while (e.MoveNext())
{
buffer.Enqueue(e.Current);
checked
{
++count;
}
if (count > to.Value)
{
var idx = count - bufferCap;
if (idx > range.Start.Value && idx <= range.End.Value)
{
move.Enqueue(buffer.Dequeue());
}
else
{
yield return buffer.Dequeue();
}
}
}
while (move.TryDequeue(out var element))
{
yield return element;
}
while (buffer.TryDequeue(out var element))
{
yield return element;
}
}
yield break;
case (false, true, false):
// [4, 5, 2, 4, 1, §, 5] Move(1..^4, 2)
break;
case (false, true, true):
// [4, 5, 2, 4, 1, §, 5] Move(1..^4, ^2)
break;
case (true, false, false):
// [4, 5, 2, 4, 1, §, 5] Move(^5..4, 2)
break;
case (true, false, true):
// [4, 5, 2, 4, 1, §, 5] Move(^5..4, ^2)
break;
case (true, true, false):
if (range.End.Value > range.Start.Value)
{
yield break;
}
// [4, 5, 2, 4, 1, §, 5] Move(^5..^2, 4)
// Cannot yield any elements until count is known.
// Once count is known, can proceed to yield elements
break;
case (true, true, true):
// [4, 5, 2, 4, 1, §, 5] Move(^5..^3, ^2)
break;
}
}
}
else
{
foreach (
var e in Move(
source,
range.Start.Value,
range.End.Value - range.Start.Value,
to.Value
)
)
{
yield return e;
}
}
}
}
1 change: 1 addition & 0 deletions Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey, TResult>
static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TLeft, TResult>! leftResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, System.Index to) -> System.Collections.Generic.IEnumerable<T>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft? Left, TRight Right)>!
static SuperLinq.SuperEnumerable.RightOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
Expand Down
1 change: 1 addition & 0 deletions Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey, TResult>
static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TLeft, TResult>! leftResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, System.Index to) -> System.Collections.Generic.IEnumerable<T>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft? Left, TRight Right)>!
static SuperLinq.SuperEnumerable.RightOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
Expand Down
1 change: 1 addition & 0 deletions Source/SuperLinq/PublicAPI/net8.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey, TResult>
static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TLeft, TResult>! leftResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, System.Index to) -> System.Collections.Generic.IEnumerable<T>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft? Left, TRight Right)>!
static SuperLinq.SuperEnumerable.RightOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey, TResult>
static SuperLinq.SuperEnumerable.LeftOuterLoopJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TLeft, TResult>! leftResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.LeftOuterMergeJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft Left, TRight? Right)>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, System.Index to) -> System.Collections.Generic.IEnumerable<T>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
static SuperLinq.SuperEnumerable.RightOuterHashJoin<TLeft, TRight, TKey>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<(TLeft? Left, TRight Right)>!
static SuperLinq.SuperEnumerable.RightOuterMergeJoin<TLeft, TRight, TKey, TResult>(this System.Collections.Generic.IEnumerable<TLeft>! left, System.Collections.Generic.IEnumerable<TRight>! right, System.Func<TLeft, TKey>! leftKeySelector, System.Func<TRight, TKey>! rightKeySelector, System.Func<TRight, TResult>! rightResultSelector, System.Func<TLeft, TRight, TResult>! bothResultSelector, System.Collections.Generic.IComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<TResult>!
Expand Down
Loading