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



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



Edit



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

594   9  

9 ответов:

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

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

звучит как

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

а ты пишешь по-Линковски

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

2-е изд:

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

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

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

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

Цикл

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

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

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

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

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

выход

enter image description here

имхо ни один ответ не является правильным. Все решения начинаются с 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];
}

Comments

    Ничего не найдено.