Skip to content

Commit 5b25a39

Browse files
I've added a Skip(int count) method to the IntSet class. This method provides an IEnumerable<int> that leaves out the initial count elements from the set (when considering them in their natural ascending order) and then provides the rest.
To do this, I made use of the existing `GetElementsInRange` method: - If `count` is zero or less, all elements are given back. - If `count` is the same as or larger than the total number of elements, you'll get an empty list. - In other cases, I find the element at the `count`-th spot and then use `GetElementsInRange` to give you all the elements that come after it, including the one at the `count`-th position. I've also put thorough unit tests into `IntSetTests.cs` to check many different situations, such as: - Empty sets. - When `count` is zero, negative, the same as the set size, or bigger than the set size. - Skipping some elements in both small and large sets. - Sets that include positive numbers, negative numbers, and zero. These tests confirm that the elements are correct and are in ascending order.
1 parent ea76af7 commit 5b25a39

2 files changed

Lines changed: 101 additions & 0 deletions

File tree

src/IntSet.Tests/IntSetTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,5 +605,56 @@ public void GetElementsInRange_DeepTraversal()
605605
}
606606

607607
#endregion
608+
609+
#region Skip Tests
610+
611+
[Theory]
612+
[InlineData(new int[] { }, 0, new int[] { })]
613+
[InlineData(new int[] { }, 1, new int[] { })]
614+
[InlineData(new int[] { }, -1, new int[] { })]
615+
[InlineData(new[] { 1, 2, 3 }, 0, new[] { 1, 2, 3 })]
616+
[InlineData(new[] { 1, 2, 3 }, -2, new[] { 1, 2, 3 })] // Negative count should be like 0
617+
[InlineData(new[] { 1, 2, 3 }, 1, new[] { 2, 3 })]
618+
[InlineData(new[] { 1, 2, 3 }, 2, new[] { 3 })]
619+
[InlineData(new[] { 1, 2, 3 }, 3, new int[] { })] // Count equals length
620+
[InlineData(new[] { 1, 2, 3 }, 4, new int[] { })] // Count greater than length
621+
[InlineData(new[] { -5, -2, 0, 3, 7 }, 0, new[] { -5, -2, 0, 3, 7 })]
622+
[InlineData(new[] { -5, -2, 0, 3, 7 }, 2, new[] { 0, 3, 7 })]
623+
[InlineData(new[] { -5, -2, 0, 3, 7 }, 4, new[] { 7 })]
624+
[InlineData(new[] { -5, -2, 0, 3, 7 }, 5, new int[] { })]
625+
[InlineData(new[] { -5, -2, 0, 3, 7 }, 6, new int[] { })]
626+
[InlineData(new[] { -5, -2, 0, 3, 7 }, -5, new[] { -5, -2, 0, 3, 7 })]
627+
public void Skip_VariousScenarios(int[] setData, int count, int[] expectedData)
628+
{
629+
// Arrange
630+
var set = new Kibnet.IntSet(setData);
631+
var expected = expectedData.ToList();
632+
633+
// Act
634+
var actual = set.Skip(count).ToList();
635+
636+
// Assert
637+
Assert.Equal(expected, actual); // Assert.Equal on lists checks order and content
638+
}
639+
640+
[Fact]
641+
public void Skip_LargeSet_ReturnsCorrectSubsetsAndOrder()
642+
{
643+
// Arrange
644+
var largeSetData = Enumerable.Range(0, 1000).ToArray(); // Creates {0, 1, ..., 999}
645+
var set = new Kibnet.IntSet(largeSetData);
646+
647+
// Act & Assert
648+
// Compare with LINQ's Skip behavior
649+
Assert.Equal(largeSetData.Skip(0).ToList(), set.Skip(0).ToList());
650+
Assert.Equal(largeSetData.Skip(100).ToList(), set.Skip(100).ToList());
651+
Assert.Equal(largeSetData.Skip(500).ToList(), set.Skip(500).ToList());
652+
Assert.Equal(largeSetData.Skip(999).ToList(), set.Skip(999).ToList());
653+
Assert.Equal(largeSetData.Skip(1000).ToList(), set.Skip(1000).ToList()); // Should be empty
654+
Assert.Equal(largeSetData.Skip(1001).ToList(), set.Skip(1001).ToList()); // Should be empty
655+
Assert.Equal(largeSetData.Skip(-10).ToList(), set.Skip(-10).ToList()); // Negative, should return all
656+
}
657+
658+
#endregion
608659
}
609660
}

src/IntSet/IntSet.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,56 @@ public IEnumerable<int> GetElementsInRange(int firstElement, int lastElement)
916916
}
917917
}
918918

919+
/// <summary>
920+
/// Skips a specified number of elements in a sequence and then returns the remaining elements.
921+
/// </summary>
922+
/// <param name="count">The number of elements to skip before returning the remaining elements.</param>
923+
/// <returns>An <see cref="IEnumerable{T}"/> that contains the elements that occur after the specified index in the input sequence.</returns>
924+
public IEnumerable<int> Skip(int count)
925+
{
926+
if (count <= 0)
927+
{
928+
// Return all elements in ascending order
929+
foreach (var item in this)
930+
{
931+
yield return item;
932+
}
933+
yield break;
934+
}
935+
936+
if (count >= this.LongCount)
937+
{
938+
// Return empty if count is too large
939+
yield break;
940+
}
941+
942+
int? elementToStartFrom = null;
943+
long elementsSkipped = 0; // Use long to match LongCount
944+
945+
// Iterate to find the (count)-th element (0-indexed).
946+
// This element is the first one to be included.
947+
foreach (var item in this) // 'this' iterates in ascending order
948+
{
949+
if (elementsSkipped == count)
950+
{
951+
elementToStartFrom = item;
952+
break;
953+
}
954+
elementsSkipped++;
955+
}
956+
957+
if (elementToStartFrom.HasValue)
958+
{
959+
// GetElementsInRange is inclusive of its first parameter.
960+
foreach (var itemInRange in GetElementsInRange(elementToStartFrom.Value, int.MaxValue))
961+
{
962+
yield return itemInRange;
963+
}
964+
}
965+
// If elementToStartFrom is null (e.g., if count == LongCount, though caught earlier),
966+
// this correctly yields nothing.
967+
}
968+
919969
private static (int Min, int Max) GetBlockRange(int i0 = -1, int i1 = -1, int i2 = -1, int i3 = -1)
920970
{
921971
int minBase = 0;

0 commit comments

Comments
 (0)