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
28 changes: 27 additions & 1 deletion Source/SuperLinq/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,30 @@ 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="toIndex">
/// The index where the specified range will be moved.</param>
/// <returns>
/// A sequence with the specified range moved to the new position.
/// </returns>
/// <remarks>
/// This operator uses deferred execution and streams its results.
/// </remarks>
/// <example>
/// <code><![CDATA[
/// var result = Enumerable.Range(0, 6).Move(3..5, 0);
/// ]]></code>
/// The <c>result</c> variable will contain <c>{ 3, 4, 0, 1, 2, 5 }</c>.
/// </example>
public static IEnumerable<T> Move<T>(this IEnumerable<T> source, Range range, int toIndex)
{
return source.Move(range.Start.Value, range.End.Value - range.Start.Value, toIndex);
}
}
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 @@ -4,3 +4,4 @@
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Func<TKey, TAccumulate>! seedSelector, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, TAccumulate seed, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.Take<TSource>(System.Collections.Generic.IEnumerable<TSource>! source, System.Range range) -> System.Collections.Generic.IEnumerable<TSource>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, int toIndex) -> System.Collections.Generic.IEnumerable<T>!
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 @@ -4,3 +4,4 @@
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Func<TKey, TAccumulate>! seedSelector, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, TAccumulate seed, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.Take<TSource>(System.Collections.Generic.IEnumerable<TSource>! source, System.Range range) -> System.Collections.Generic.IEnumerable<TSource>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, int toIndex) -> System.Collections.Generic.IEnumerable<T>!
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 @@ -4,3 +4,4 @@
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Func<TKey, TAccumulate>! seedSelector, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, TAccumulate seed, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.Take<TSource>(System.Collections.Generic.IEnumerable<TSource>! source, System.Range range) -> System.Collections.Generic.IEnumerable<TSource>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, int toIndex) -> System.Collections.Generic.IEnumerable<T>!
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Func<TKey, TAccumulate>! seedSelector, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.AggregateBy<TSource, TKey, TAccumulate>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, TAccumulate seed, System.Func<TAccumulate, TSource, TAccumulate>! func, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TAccumulate>>!
static SuperLinq.SuperEnumerable.Move<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Range range, int toIndex) -> System.Collections.Generic.IEnumerable<T>!
*REMOVED*static SuperLinq.SuperEnumerable.Publish<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<System.Collections.Generic.IEnumerable<TSource>!, System.Collections.Generic.IEnumerable<TResult>!>! selector) -> System.Collections.Generic.IEnumerable<TResult>!
*REMOVED*static SuperLinq.SuperEnumerable.Share<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<System.Collections.Generic.IEnumerable<TSource>!, System.Collections.Generic.IEnumerable<TResult>!>! selector) -> System.Collections.Generic.IEnumerable<TResult>!
95 changes: 94 additions & 1 deletion Tests/SuperLinq.Test/MoveTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,40 @@ public void MoveWithNegativeFromIndex()
new[] { 1 }.Move(-1, 0, 0));
}

[Fact]
public void MoveRangeWithNegativeStartIndex()
{
_ = Assert.Throws<ArgumentOutOfRangeException>(() => new[] { 1 }.Move(-1..-1, 0));
}

[Fact]
public void MoveWithNegativeCount()
{
_ = Assert.Throws<ArgumentOutOfRangeException>(() =>
new[] { 1 }.Move(0, -1, 0));
}

[Fact]
public void MoveRangeWithDecendingRange()
{
_ = Assert.Throws<ArgumentOutOfRangeException>(() =>
new[] { 1 }.Move(0..-1, 0));
}

[Fact]
public void MoveWithNegativeToIndex()
{
_ = Assert.Throws<ArgumentOutOfRangeException>(() =>
new[] { 1 }.Move(0, 0, -1));
}

[Fact]
public void MoveRangeWithNegativeToIndex()
{
_ = Assert.Throws<ArgumentOutOfRangeException>(() =>
new[] { 1 }.Move(0..0, -1));
}

[Fact]
public void MoveIsLazy()
{
Expand All @@ -44,6 +64,21 @@ public void Move(int length, int fromIndex, int count, int toIndex)
result.AssertSequenceEqual(expectations);
}

[Theory, MemberData(nameof(MoveRangeSource))]
public void MoveRange(int length, Range range, int toIndex)
{
var source = Enumerable.Range(0, length);

using var test = source.AsTestingSequence();

var result = test.Move(range, toIndex);

var slice = source.Take(range);
var exclude = source.Exclude(range.Start.Value, range.End.Value - range.Start.Value);
var expectations = exclude.Take(toIndex).Concat(slice).Concat(exclude.Skip(toIndex));
result.AssertSequenceEqual(expectations);
}

public static IEnumerable<object[]> MoveSource()
{
const int Length = 10;
Expand All @@ -58,6 +93,20 @@ from count in Enumerable.Range(0, Length + 1)
select tcd;
}

public static IEnumerable<object[]> MoveRangeSource()
{
const int Length = 10;
return
from index in Enumerable.Range(0, Length)
from count in Enumerable.Range(0, Length + 1)
from tcd in new object[][]
{
[Length, index..(index + count), Math.Max(0, index - 1),],
[Length, index..(index + count), index + 1,],
}
select tcd;
}

[Theory, MemberData(nameof(MoveWithSequenceShorterThanToIndexSource))]
public void MoveWithSequenceShorterThanToIndex(int length, int fromIndex, int count, int toIndex)
{
Expand All @@ -71,10 +120,27 @@ public void MoveWithSequenceShorterThanToIndex(int length, int fromIndex, int co
Assert.Equal(expectations, result);
}

[Theory, MemberData(nameof(MoveRangeWithSequenceShorterThanToIndexSource))]
public void MoveRangeWithSequenceShorterThanToIndex(int length, Range range, int toIndex)
{
var source = Enumerable.Range(0, length);

using var test = source.AsTestingSequence();

var result = test.Move(range, toIndex);

var expectations = source.Exclude(range.Start.Value, range.End.Value - range.Start.Value).Concat(source.Take(range));
Assert.Equal(expectations, result);
}

public static IEnumerable<object[]> MoveWithSequenceShorterThanToIndexSource() =>
Enumerable.Range(10, 10 + 5)
.Select(toIndex => new object[] { 10, 5, 2, toIndex, });

public static IEnumerable<object[]> MoveRangeWithSequenceShorterThanToIndexSource() =>
Enumerable.Range(10, 10 + 5)
.Select(toIndex => new object[] { 10, 5..7, toIndex, });

[Fact]
public void MoveIsRepeatable()
{
Expand All @@ -84,6 +150,15 @@ public void MoveIsRepeatable()
Assert.Equal(result, result.ToArray());
}

[Fact]
public void MoveRangeIsRepeatable()
{
using var source = Enumerable.Range(0, 10).AsTestingSequence(maxEnumerations: 2);

var result = source.Move(0..5, 10);
Assert.Equal(result, result.ToArray());
}

[Fact]
public void MoveWithFromIndexEqualsToIndex()
{
Expand All @@ -93,6 +168,15 @@ public void MoveWithFromIndexEqualsToIndex()
result.AssertSequenceEqual(Enumerable.Range(0, 10));
}

[Fact]
public void MoveRangeWithFomrIndexEqualsToIndex()
{
using var source = Enumerable.Range(0, 10).AsTestingSequence();

var result = source.Move(5..1004, 5);
result.AssertSequenceEqual(Enumerable.Range(0, 10));
}

[Fact]
public void MoveWithCountEqualsZero()
{
Expand All @@ -101,4 +185,13 @@ public void MoveWithCountEqualsZero()
var result = source.Move(5, 0, 999);
result.AssertSequenceEqual(Enumerable.Range(0, 10));
}
}

[Fact]
public void MoveRngeWithCountEqualsZero()
{
using var source = Enumerable.Range(0, 10).AsTestingSequence();

var result = source.Move(5..5, 999);
result.AssertSequenceEqual(Enumerable.Range(0, 10));
}
}