我正在使用.NET 3.5,并且希望能够从列表中获取每个* n
*项。我对使用lambda表达式还是LINQ来实现它并不感到困扰。
修改
看起来这个问题引起了很多争论(这是一件好事,对吧?)。我学到的主要内容是,当你认为你知道做某事的每一种方式时(尽管这很简单),再想一想!
答案 0 :(得分:170)
return list.Where((x, i) => i % nStep == 0);
答案 1 :(得分:36)
我知道这是“老派”,但为什么不使用带有步进= n的for循环?
答案 2 :(得分:33)
听起来像
IEnumerator<T> GetNth<T>(List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i]
}
会做到这一点。我认为不需要使用Linq或lambda表达式。
修改强>
成功
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];
}
}
你用LINQish方式写作
from var element in MyList.GetNth(10) select element;
第二次修改:
使其更加LINQish
from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i];
答案 3 :(得分:25)
您可以使用传递索引的Where重载以及元素
var everyFourth = list.Where((x,i) => i % 4 == 0);
答案 4 :(得分:10)
For Loop
for(int i = 0; i < list.Count; i += n)
//Nth Item..
答案 5 :(得分:3)
我不确定是否可以使用LINQ表达式,但我知道您可以使用Where
扩展方法来执行此操作。例如,获取每五个项目:
List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList();
这将获得第一个项目,并从那里获得第五个项目。如果你想从第五个项目开始而不是从第一个项目开始,则用4进行比较,而不是与0进行比较。
答案 6 :(得分:3)
我认为如果你提供一个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];
}
}
答案 7 :(得分:0)
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();
}
输出
答案 8 :(得分:0)
Imho没有回答是对的。所有解决方案都从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];
}
答案 9 :(得分:0)
@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];
}
}