user2361573
user2361573

Reputation: 29

Performance of Skip and Take in Linq to Objects

"Searching for alternative functionalities for "Skip" and "Take" functionalities"

1 of the link says "Everytime you invoke Skip() it will have to iterate you collection from the beginning in order to skip the number of elements you desire, which gives a loop within a loop (n2 behaviour)"

Conclusion: For large collections, don’t use Skip and Take. Find another way to iterate through your collection and divide it.

In order to access last page data in a huge collection, can you please suggest us a way other than Skip and Take approach?

Upvotes: 1

Views: 4878

Answers (3)

Maxim
Maxim

Reputation: 13458

Internally it is really correct:

private static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count)
{
  using (IEnumerator<TSource> enumerator = source.GetEnumerator())
  {
    while (count > 0 && enumerator.MoveNext())
      --count;
    if (count <= 0)
    {
      while (enumerator.MoveNext())
        yield return enumerator.Current;
    }
  }
}

If you want to skip for IEnumerable<T> then it works right. There are no other way except enumeration to get specific element(s). But you can write own extension method on IReadOnlyList<T> or IList<T> (if this interface is implemented in collection used for your elements).

public static class IReadOnlyListExtensions
{
    public static IEnumerable<T> Skip<T>(this IReadOnlyList<T> collection, int count)
    {
        if (collection == null)
            return null;

        return ICollectionExtensions.YieldSkip(collection, count);
    }

    private static IEnumerable<T> YieldSkip<T>(IReadOnlyList<T> collection, int count)
    {
        for (int index = count; index < collection.Count; index++)
        {
            yield return collection[index];
        }
    }
}

In addition you can implement it for IEnumerable<T> but check inside for optimization:

if (collection is IReadOnlyList<T>)
{
    // do optimized skip
}

Such solution is used a lot of where in Linq source code (but not in Skip unfortunately).

Upvotes: 1

Dennis_E
Dennis_E

Reputation: 8894

Looking at the source for Skip, you can see it enumerates over all the items, even over the first n items you want to skip.
It's strange though, because several LINQ-methods have optimizations for collections, like Count and Last.
Skip apparently does not.

If you have an array or IList<T>, you use the indexer to truly skip over them:

for (int i = skipStartIndex; i < list.Count; i++) {
    yield return list[i];
}

Upvotes: 2

Alexey Khoroshikh
Alexey Khoroshikh

Reputation: 435

Depends on your implementation, but it would make sense to use indexed arrays for the purpose, instead.

Upvotes: 0

Related Questions