开发者

Take every 2nd object in list

开发者 https://www.devze.com 2023-01-13 05:39 出处:网络
I ha开发者_如何学Cve an IEnumerable and I want to get a new IEnumerable containing every nth element.

I ha开发者_如何学Cve an IEnumerable and I want to get a new IEnumerable containing every nth element.

Can this be done in Linq?


Just figured it out myself...

The IEnumerable<T>.Where() method has an overload that takes the index of the current element - just what the doctor ordered.

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

This would return

{1, 3, 5}

Update: In order to cover both my use case and Dan Tao's suggestion, let's also specify what the first returned element should be:

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

...would return

{2, 4}


To implement Cristi's suggestion:

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

Usage:

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

var evens = upToTen.Sample(2);
var multiplesOfThree = upToTen.Sample(3);


While not LINQ you may also create an extension method with 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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号