C# 如何从 List<T> 中获取每个第 n 个项目?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/682615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get every nth item from a List<T>?
提问by Paul Suart
I'm using .NET 3.5 and would like to be able to obtain every *n
*th item from a List. I'm not bothered as to whether it's achieved using a lambda expression or LINQ.
我正在使用 .NET 3.5 并且希望能够n
从列表中获取每个 * *th 项。我并不担心它是使用 lambda 表达式还是 LINQ 实现的。
Edit
编辑
Looks like this question provoked quite a lot of debate (which is a good thing, right?). The main thing I've learnt is that when you think you know every way to do something (even as simple as this), think again!
看起来这个问题引起了很多争论(这是一件好事,对吧?)。我学到的主要事情是,当您认为自己知道做某事的所有方法时(即使像这样简单),请再想一想!
采纳答案by mqp
return list.Where((x, i) => i % nStep == 0);
回答by Michael Todd
I know it's "old school," but why not just use a for loop with stepping = n?
我知道这是“老派”,但为什么不直接使用带有 stepping = n 的 for 循环?
回答by Quintin Robinson
For Loop
For循环
for(int i = 0; i < list.Count; i += n)
//Nth Item..
回答by MartinStettner
Sounds like
听起来好像
IEnumerator<T> GetNth<T>(List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i]
}
would do the trick. I do not see the need to use Linq or a lambda expressions.
会做的伎俩。我认为不需要使用 Linq 或 lambda 表达式。
EDIT:
编辑:
Make it
做了
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];
}
}
and you write in a LINQish way
你用LINQish的方式写
from var element in MyList.GetNth(10) select element;
2nd Edit:
第二次编辑:
To make it even more LINQish
让它更加 LINQish
from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i];
回答by JaredPar
You can use the Where overload which passes the index along with the element
您可以使用将索引与元素一起传递的 Where 重载
var everyFourth = list.Where((x,i) => i % 4 == 0);
回答by Guffa
I'm not sure if it's possible to do with a LINQ expression, but I know that you can use the Where
extension method to do it. For example to get every fifth item:
我不确定是否可以使用 LINQ 表达式,但我知道您可以使用Where
扩展方法来做到这一点。例如获取每五个项目:
List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList();
This will get the first item and every fifth from there. If you want to start at the fifth item instead of the first, you compare with 4 instead of comparing with 0.
这将获得第一个项目,从那里每五个项目。如果要从第五项而不是第一项开始,则与 4 进行比较而不是与 0 进行比较。
回答by belucha
I think if you provide a linq extension, you should be able to operate on the least specific interface, thus on IEnumerable. Of course, if you are up for speed especially for large N you might provide an overload for indexed access. The latter removes the need of iterating over large amounts of not needed data, and will be much faster than the Where clause. Providing both overloads lets the compiler select the most suitable variant.
我认为如果您提供 linq 扩展,您应该能够在最不具体的界面上进行操作,即在 IEnumerable 上。当然,如果您想加快速度,尤其是对于大 N,您可能会为索引访问提供过载。后者消除了对大量不需要的数据进行迭代的需要,并且比 Where 子句快得多。提供这两种重载可以让编译器选择最合适的变体。
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];
}
}
回答by Anwar Ul Haq
回答by user2340145
Imho no answer is right. All solutions begins from 0. But I want to have the real nth element
恕我直言,没有答案是正确的。所有解决方案都从 0 开始。但我想要真正的第 n 个元素
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];
}
回答by Spoc
@belucha I like this, because the client code is very readable and the Compiler chooses the most efficient Implementation. I would build upon this by reducing the requirements to IReadOnlyList<T>
and to save the Division for high-performance LINQ:
@belucha 我喜欢这个,因为客户端代码非常易读,编译器会选择最有效的实现。我将在此基础上减少对IReadOnlyList<T>
高性能 LINQ的要求并保存该部门:
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];
}
}