Как я могу получить каждый n-й элемент из списка <T>?

Я использую .NET 3.5 и хотел бы получить каждый * n * -й элемент из списка. Я не беспокоюсь о том, достигнуто ли это с помощью лямбда-выражения или LINQ.

Edit

Похоже, этот вопрос вызвал довольно много дебатов (что хорошо, правда?). Главное, что я узнал, это то, что, когда вы думаете, что знаете каждый способ сделать что-то (даже так просто), подумайте еще раз!

Ответ 1

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

Ответ 2

Я знаю это "старая школа", но почему бы просто не использовать цикл for с stepping = n?

Ответ 3

Звучит как

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

сделал бы трюк. Я не вижу необходимости использовать Linq или лямбда-выражения.

EDIT:

Сделать это

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

и вы пишете LINKish способом

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

2nd Edit:

Чтобы сделать его еще более LINQish

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

Ответ 4

Вы можете использовать Перегрузку Where, которая передает индекс вместе с элементом

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

Ответ 5

Для цикла

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

Ответ 6

Я не уверен, возможно ли это сделать с выражением LINQ, но я знаю, что для этого можно использовать метод расширения Where. Например, чтобы получить каждый пятый элемент:

List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList();

Это получит первый элемент и каждую пятую оттуда. Если вы хотите начать с пятого элемента вместо первого, вы сравниваете с 4 вместо сравнения с 0.

Ответ 7

Я думаю, что если вы предоставите расширение 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];
    }
}

Ответ 8

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();
}

Выход

введите описание изображения здесь