Take every 2nd object in list

I have an IEnumerable and I want to get a new IEnumerable containing every nth element.

Can this be done in Linq?

7
задан Isaac 25 August 2010 в 16:18
поделиться

3 ответа

Только что сам разобрался...

Метод IEnumerable.Where() имеет перегрузку, которая берет индекс текущего элемента — как раз то, что доктор прописал.

(new []{1,2,3,4,5}).Where((elem, idx) => idx % 2 == 0);

Это вернет

{1, 3, 5}

Обновление: чтобы охватить как мой вариант использования, так и предложение Дэна Тао, давайте также укажем, каким должен быть первый возвращаемый элемент:

var firstIdx = 1;
var takeEvery = 2;
var list =  new []{1,2,3,4,5};

var newList = list
    .Skip(firstIdx)
    .Where((elem, idx) => idx % takeEvery == 0);

...будет возвращаться

{2, 4}
23
ответ дан 6 December 2019 в 05:54
поделиться

Для реализации предложения Кристи :

public static IEnumerable<T> Sample<T>(this IEnumerable<T> source, int interval)
{
    // null check, out of range check go here

    return source.Where((value, index) => (index + 1) % interval == 0);
}

Использование:

var upToTen = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

var evens = upToTen.Sample(2);
var multiplesOfThree = upToTen.Sample(3);
8
ответ дан 6 December 2019 в 05:54
поделиться

Хотя это и не LINQ, вы также можете создать метод расширения с yield.

public static IEnumerable<T> EverySecondObject<T>(this IEnumerable<T> list)
{
    using (var enumerator = list.GetEnumerator())
    {
        while (true)
        {
            if (!enumerator.MoveNext())
                yield break;
            if (enumerator.MoveNext())
                yield return enumerator.Current;
            else
                yield break;
        }
    }
}
0
ответ дан 6 December 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: