To get every nth element in a list, a solution is to do mylist[::n].
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With