Как я могу получить каждый N-й элемент из списка?
Я использую .NET 3.5 и хотел бы иметь возможность получить каждый *n * й пункт из списка. Я не беспокоюсь о том, достигается ли это с помощью лямбда-выражения или LINQ.
Edit
похоже, этот вопрос вызвал довольно много споров (что хорошо, не так ли?). Главное, что я узнал, это то, что когда вы думаете, что знаете все способы сделать что-то (даже так просто, как это), подумайте еще раз!
9 ответов:
звучит как
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);
Я не уверен, что это возможно сделать с выражением 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]; } }
имхо ни один ответ не является правильным. Все решения начинаются с 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