如何从List <T>中获取每个第n项?

Pau*_*art 108 c# linq lambda list

我正在使用.NET 3.5,并希望能够n从列表中获取每个**项.我对使用lambda表达式还是LINQ实现它并不感到困扰.

编辑

看起来这个问题激起了很多争论(这是一件好事,对吧?).我学到的主要是,当你认为你知道每一种做某事的方式时(尽管这很简单),再想一想!

mqp*_*mqp 180

return list.Where((x, i) => i % nStep == 0);
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的是:Linq/Lambda解决方案的性能远低于具有固定增量的简单循环. (5认同)
  • 不一定,通过延迟执行,它可以在foreach循环中使用,并且只在原始列表上循环一次. (5认同)
  • @mquander:请注意,这实际上会给你第n - 1个元素.如果你想要实际的第n个元素(跳过第一个元素)那么你将不得不向i添加1. (3认同)
  • 是的,我想这有点取决于你所说的"第n",但你的解释可能更为常见.根据您的需要添加或减少i. (2认同)
  • 这取决于你所说的“实用”是什么意思。如果您需要一种在用户单击按钮时快速获取 30 个项目列表中的所有其他项目的方法,我会说这非常实用。有时性能真的不再重要了。当然,有时确实如此。 (2认同)

Mic*_*odd 37

我知道这是"老派",但为什么不使用带有步进= n的for循环?

  • @casperOne:我相信程序员发明了这个叫做子程序的东西来处理这个问题;)在一个真正的程序中,我可能会使用一个循环,尽管有一个聪明的LINQ版本,因为循环意味着你不必遍历每个元素(将索引增加N.) (8认同)
  • @Michael Todd:它有效,但问题是您必须在各处复制该功能。通过使用 LINQ,它成为组合查询的一部分。 (2认同)

Mar*_*ner 33

听起来好像

IEnumerator<T> GetNth<T>(List<T> list, int n) {
  for (int i=0; i<list.Count; i+=n)
    yield return list[i]
}
Run Code Online (Sandbox Code Playgroud)

会做的伎俩.我没有看到使用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];
  }
}
Run Code Online (Sandbox Code Playgroud)

你用LINQish的方式写作

from var element in MyList.GetNth(10) select element;
Run Code Online (Sandbox Code Playgroud)

第二编辑:

为了使它更加LINQish

from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i];
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这种使用this [] getter而不是Where()方法的方法,它基本上迭代了IEnumerable的每个元素.如果你有一个IList/ICollection类型,这是更好的方法,恕我直言. (2认同)

Jar*_*Par 25

您可以使用Where过载将索引与元素一起传递

var everyFourth = list.Where((x,i) => i % 4 == 0);
Run Code Online (Sandbox Code Playgroud)


Qui*_*son 10

对于循环

for(int i = 0; i < list.Count; i += n)
    //Nth Item..
Run Code Online (Sandbox Code Playgroud)


小智 6

我认为如果您提供 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];
    }
}
Run Code Online (Sandbox Code Playgroud)