How can I get every nth item from a List<T>?
我正在使用.NET 3.5,希望能够从列表中获取每个*
编辑
看起来这个问题引起了很多争论(这是好事,对吧?)我学到的最主要的一点是,当你认为你知道做某件事的所有方法(即使如此简单)时,再想想!
1 | return list.Where((x, i) => i % nStep == 0); |
号
我知道这是"老派",但为什么不使用一个for循环,stepping=n?
听起来像
1 2 3 4 | IEnumerator<T> GetNth<T>(List<T> list, int n) { for (int i=0; i<list.Count; i+=n) yield return list[i] } |
会成功的。我不认为需要使用LINQ或lambda表达式。
编辑:
成功
1 2 3 4 5 6 | public static class MyListExtensions { public static IEnumerable<T> GetNth<T>(this List<T> list, int n) { for (int i=0; i<list.Count; i+=n) yield return list[i]; } } |
。
你的写作方式很简单
1 | from var element in MyList.GetNth(10) select element; |
第二次编辑:
使之更具灵气
1 | from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i]; |
。
可以使用Where重载,该重载与元素一起传递索引。
1 | var everyFourth = list.Where((x,i) => i % 4 == 0); |
。
for循环
1 2 | for(int i = 0; i < list.Count; i += n) //Nth Item.. |
我认为如果您提供一个LINQ扩展,您应该能够在最不特定的接口上操作,从而在IEnumerable上操作。当然,如果您提高了速度,特别是对于大型N,那么可能会为索引访问提供过载。后者消除了对大量不需要的数据进行迭代的需要,并且比WHERE子句快得多。提供这两个重载可以让编译器选择最合适的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static class LinqExtensions { public static IEnumerable<T> GetNth<T>(this IEnumerable<T> list, int n) { if (n < 0) throw new ArgumentOutOfRangeException("n"); if (n > 0) { int c = 0; foreach (var e in list) { if (c % n == 0) yield return e; c++; } } } public static IEnumerable<T> GetNth<T>(this IList<T> list, int n) { if (n < 0) throw new ArgumentOutOfRangeException("n"); if (n > 0) for (int c = 0; c < list.Count; c += n) yield return list[c]; } } |
。
我不确定是否可以使用LINQ表达式,但我知道您可以使用
1 | List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList(); |
这将得到第一个项目和每五个从那里。如果你想从第五项开始而不是从第一项开始,你可以用4来比较,而不是用0来比较。
@Belucha我喜欢这样,因为客户机代码可读性很好,编译器选择了最有效的实现。在此基础上,我将减少对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public static IEnumerable<T> GetNth<T>(this IEnumerable<T> list, int n) { if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null); int i = n; foreach (var e in list) { if (++i < n) { //save Division continue; } i = 0; yield return e; } } public static IEnumerable<T> GetNth<T>(this IReadOnlyList<T> list, int n , int offset = 0) { //use IReadOnlyList<T> if (n <= 0) throw new ArgumentOutOfRangeException(nameof(n), n, null); for (var i = offset; i < list.Count; i += n) { yield return list[i]; } } |
号
我不知道答案是对的。所有解决方案都从0开始。但是我想要真正的n个元素
1 2 3 4 5 | public static IEnumerable<T> GetNth<T>(this IList<T> list, int n) { for (int i = n - 1; i < list.Count; i += n) yield return list[i]; } |
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private static readonly string[] sequence ="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15".Split(','); static void Main(string[] args) { var every4thElement = sequence .Where((p, index) => index % 4 == 0); foreach (string p in every4thElement) { Console.WriteLine("{0}", p); } Console.ReadKey(); } |
输出
。