How can I take n elements from a m elements collection so that if I run out of elements it starts from the beginning?
List<int> list = new List<int>() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<int> newList = list.Skip(9).Take(2).ToList();
List<int> expected = new List(){10,1};
CollectionAssert.AreEqual(expected, newList);
How can I get the expected list? I'm looking for a CircularTake() function or something in that direction.
To get the last N elements of an array, call the slice method on the array, passing in -n as a parameter, e.g. arr. slice(-3) returns a new array containing the last 3 elements of the original array. Copied!
The remove() method removes the first matching element (which is passed as an argument) from the list. The pop() method removes an element at a given index, and will also return the removed item. You can also use the del keyword in Python to remove an element or slice from a list.
use an extension method to circular repeat the enumerable
public static IEnumerable<T> Circular<T>( this IEnumerable<T> source )
{
while (true)
foreach (var item in source)
yield return item;
}
and you can use your code
List<int> list = new List<int>() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<int> newList = list.Circular().Skip(9).Take(2).ToList();
.net fiddle example
You don't need to track the overflow because we can use the %
modulus operator (which returns the remainder from an integer division) to continually loop through a range of indexes, and it will always return a valid index in the collection, wrapping back to 0
when it gets to the end (and this will work for multiple wraps around the end of the list):
List<int> list = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<int> newList = new List<int>();
for (int skip = 9, take = 2; take > 0; skip++, take--)
{
newList.Add(list[skip % list.Count]);
}
Result:
// newList == { 10, 1 }
This could be extracted into an extension method:
public static List<T> SkipTakeWrap<T>(this List<T> source, int skip, int take)
{
var newList = new List<T>();
while (take > 0)
{
newList.Add(source[skip % source.Count]);
skip++;
take--;
}
return newList;
}
And then it could be called like:
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<int> newList = list.SkipTakeWrap(9, 2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With