取 n 个元素。如果最后从头开始

sum*_*Out 10 c# linq

如何从 am 元素集合中取出 n 个元素,以便如果我用完元素,它会从头开始?

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);
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到预期的列表?我正在寻找一个 CircularTake() 函数或那个方向的东西。

Sir*_*ufo 10

使用扩展方法循环重复可枚举

public static IEnumerable<T> Circular<T>( this IEnumerable<T> source )
{
    while (true)
        foreach (var item in source) 
            yield return item;
}
Run Code Online (Sandbox Code Playgroud)

你可以使用你的代码

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();
Run Code Online (Sandbox Code Playgroud)

.net 小提琴示例


Ruf*_*s L 9

您不需要跟踪溢出,因为我们可以使用%模运算符(它返回整数除法的余数)来不断循环遍历一系列索引,并且它将始终返回集合中的有效索引,然后返回到0当它结束时(这将适用于列表末尾的多次环绕):

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]);
}
Run Code Online (Sandbox Code Playgroud)

结果:

// newList == { 10, 1 }
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


这可以提取到扩展方法中:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后它可以被称为:

List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<int> newList = list.SkipTakeWrap(9, 2);
Run Code Online (Sandbox Code Playgroud)