首页 > 解决方案 > C# GetRange 包装

问题描述

我想问一下是否有与 List.GetRange(id,count) 类似的方法但已包装。它接受超过索引的正负起始 id 和计数。当超出集合时,元素会从头开始获取吗?

我想到的唯一方法是:

List<T> e = new List<T>{a,b,c,d,e,f};

int start=4%e.Count;
int n= 5;
List<T> eNew = new List<T>(n);


for (int i=start; i<start+n i++)
   eNew.Add(e[i%e.Count]);

是否有任何现有的类似内置命令可以执行此操作或更快?

标签: c#

解决方案


我不相信有这样的方法。当然,必须小心确保这样的功能预期会以这种方式运行。如果编码人员认为如果超出范围会得到错误,反而会得到结果,那将是不好的。

但是为了您自己的方便,您可以自己创建一个通用的扩展方法。我在下面做了一个。除了将循环的代码之外,此代码将允许从负索引开始。甚至除此之外,它将允许负长度。

public static class MyExtensions {

    public static List<T> GetRingedRange<T> (
        this List<T> list,
        int start, 
        int n
    ) {
    
        Func<decimal,decimal,int> trueModulo = (a,b) => {
            if (a >= 0)
                return (int)(a % b);
            var roundsToPositive = Math.Ceiling(Math.Abs(Convert.ToDecimal(a) / b));
            a += Convert.ToInt32(roundsToPositive * b);
            return (int)(a % b);
        };
    
        start = trueModulo(start, list.Count);
    
        start=start%list.Count;
        List<T> range = new List<T>();
                                
        for (
            int i=start; 
            n > 0 ? i < start + n : i > start + n; // i < or > start + n?
            i += n > 0 ? 1 : -1 // step forwards or backwards?
        ) {
           range.Add(list[trueModulo(i,list.Count)]);
        }
        
        return range;
        
    }

}

所以你可以这样做:

List<char> e = new List<char>{'a','b','c','d','e','f'};

var newRange = e.GetRingedRange(4,5); // e, f, a, b, c
newRange = e.GetRingedRange(-4,5); // c, d, e, f, a
newRange = e.GetRingedRange(4,-7); // e, d, c, b, a, f, e

推荐阅读