Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get every nth item from a List<T>?

Tags:

c#

list

lambda

linq

People also ask

How do you select every nth item in a list Python?

To get every nth element in a list, a solution is to do mylist[::n].

How do you find the nth element in a list?

Using index We can design a for loop to access the elements from the list with the in clause applied for nth index.


return list.Where((x, i) => i % nStep == 0);

I know it's "old school," but why not just use a for loop with stepping = n?


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.

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

from var element in MyList.GetNth(10) select element;

2nd Edit:

To make it even more LINQish

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

You can use the Where overload which passes the index along with the element

var everyFourth = list.Where((x,i) => i % 4 == 0);

For Loop

for(int i = 0; i < list.Count; i += n)
    //Nth Item..

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.

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];
    }
}

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:

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.