如何实现List扩展方法GetPreviousElements获取前N个元素?
实现List的GetPreviousElements扩展方法
看你的需求,核心就是要从指定索引的前一个位置开始,往前取最多N个元素,并且保持“近的在前、远的在后”的顺序——而且因为数据集很小,可读性是第一位的,那咱们就写得直白好懂就行。
先给你一个最直观的实现版本,完全用基础循环,一眼就能看明白逻辑:
public static class ListExtensions { public static List<T> GetPreviousElements<T>(this List<T> list, int index, int previousElementsCount) { // 先做参数校验,避免调用时传错参数导致奇怪的错误,这是写扩展方法的好习惯 if (list == null) throw new ArgumentNullException(nameof(list)); if (index < 0 || index >= list.Count) throw new ArgumentOutOfRangeException(nameof(index)); if (previousElementsCount < 0) throw new ArgumentOutOfRangeException(nameof(previousElementsCount)); var result = new List<T>(); // 从当前索引的前一个元素开始,往前遍历,最多取previousElementsCount个 // 用Math.Max(0, ...)保证不会取到负数索引 for (int i = index - 1; i >= Math.Max(0, index - previousElementsCount); i--) { result.Add(list[i]); } return result; } }
逻辑解释:
- 参数校验:先把无效输入挡住,避免后续代码出现莫名其妙的索引越界,可读性也更高
- 循环逻辑:从
index-1(当前元素的前一个)开始,一直往前数,直到取够previousElementsCount个元素,或者到列表开头为止 - 顺序保证:因为是从后往前遍历索引,所以添加到结果里的顺序就是最近的前元素在前,正好匹配你给出的示例(比如currentIndex=3时,先加索引2的
2m,再1的1.5m,最后0的1m,得到[2,1.5,1])
如果更喜欢用LINQ写得简洁一点,这个版本也很清晰:
public static class ListExtensions { public static List<T> GetPreviousElements<T>(this List<T> list, int index, int previousElementsCount) { if (list == null) throw new ArgumentNullException(nameof(list)); if (index < 0 || index >= list.Count) throw new ArgumentOutOfRangeException(nameof(index)); if (previousElementsCount < 0) throw new ArgumentOutOfRangeException(nameof(previousElementsCount)); // 计算要取的元素的起始索引:从index往前数N个,不能小于0 var startIndex = Math.Max(0, index - previousElementsCount); // 先取出从startIndex到index-1的片段,再反转就得到近到远的顺序 return list.GetRange(startIndex, index - startIndex).Reverse().ToList(); } }
这个版本的思路也很直白:先把要取的连续片段拿出来(比如currentIndex=4时,取索引1到3的[1.5,2,2.5]),然后反转一下,就得到[2.5,2,1.5],完全符合你的预期。
两种方案都能完美匹配你给出的测试场景,因为数据集小,性能差异可以忽略,选你读起来更顺的就行。
内容的提问来源于stack exchange,提问作者B Z
相关产品推荐
相关产品推荐

