What's the behaviour of skip and take?

FranK Duc 121 Reputation points
2021-02-26T13:40:05.263+00:00

Hello,

I am questionning myself about the behaviour of Skip and Take. I have a list of prices. I can loop using Count to get the minimum price and its index.
I can also use .Min() and IndexOf(). Both will return the same answer.

But is there a difference between using only Skip alone and Skip and Take?

For example, is there a difference between;

var sumAz = listCan.Skip(azureIndex).Take(Arest);

and

var sumAz = listCan.Skip(azureIndex);

Will it return the same answer in the same order? I do have an issue where my numbers in my list seem sliding. I still dont have a clear view of what's going on.

I am using those method to create a cumulative moving average. The CMA return the right answer but in the chart when the prices are going down the CMA is sliding. I am not sure Skip or Take are the problem.

for(int barIndex = azureIndex; barIndex <= ChartBars.ToIndex; barIndex++)

            {
            double volumesa = Bars.GetVolume(barIndex); 
                listva.Add(volumesa);
            }   

            var listMa = sumAz.Zip(listva, (first, second) => first * second);

            double resulta = listMa.Sum();

            double sumVola = listva.Sum();

            Ncmaa = resulta / sumVola;

Thank you

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,638 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 51,346 Reputation points
    2021-02-26T16:12:36.043+00:00

    The Skip extension method simply skips the given number of items. An example may be useful here and the most common usage for Skip (and Take) is with paging so that is the example I'll use.

    //Get all products from database (not a realistic call here...)
    var products = GetProducts();
    
    //Page size is 25 products and we want page 2 (products 26-50)
    var skipFive = letters.Skip(25);
    

    The original list could contain 1000s of items so the UI is going to use paging. The UI wants to show 25 items at a time so the first page shows items 1-25, the second 26-50, etc. To get to page 2 we need to skip page size items from the original list so we use Skip(25). This skips "page 1".

    Because this is IEnumerable it isn't creating a new collection in memory but simply skipping over the existing items. Since IEnumerable does not define how the data is stored and is forward only the implementation of Skip is simply a foreach that ignores the first X items. The order in which items are returned is the same order as the original collection. Skip will not modify the ordering, it just skips items.

    Take is used to limit the number of items. Most IEnumerable methods return everything from the modified list. But if you don't need everything you can use Take to truncate it. Going back to the paging example, since the page size is 25 we would only need to get the next 25 items. While we could return all of it that would be a waste of time. Take will stop returning values after it reaches the desired number.

    //Get the first page of items (25 page size)
    var pageItems = products.Take(25);
    

    As with Skip it does not create anything in memory. It simply enumerates the provided collection of items until it reaches the specified limit and then it stops. The order is always defined by the underlying collection. The method will not change the ordering.

    In summary, if I wanted to get page 2 of products where page size is 25 then it can be done this way.

    var pageSize = 25;
    var pageNumber = 2;
    var skipCount = (pageNumber - 1) * pageSize;
    var page2 = products.Skip(skipCount).Take(pageSize);  //Get page N with given page size
    

    If the order in which Skip or Take is returning items is wrong the problem is with the original collection, not the methods.

    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Karen Payne MVP 35,386 Reputation points
    2021-02-26T15:59:15.34+00:00

    Skip bypasses a specified number of elements in a sequence and then returns the remaining elements.

    public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count)  
    {  
        if (source == null)  
        {  
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);  
        }  
      
        if (count <= 0)  
        {  
            // Return source if not actually skipping, but only if it's a type from here, to avoid  
            // issues if collections are used as keys or otherwise must not be aliased.  
            if (source is Iterator<TSource> || source is IPartition<TSource>)  
            {  
                return source;  
            }  
      
            count = 0;  
        }  
        else if (source is IPartition<TSource> partition)  
        {  
            return partition.Skip(count);  
        }  
      
        return SkipIterator(source, count);  
    }  
    

    While Take returns a specified number of contiguous elements from the start of a sequence

    public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count)  
    {  
        if (source == null)  
        {  
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);  
        }  
      
        return count <= 0 ?  
            Empty<TSource>() :  
            TakeIterator<TSource>(source, count);  
    }  
    

    See also

    Return Or Skip Elements in a Sequence

    0 comments No comments

  2. FranK Duc 121 Reputation points
    2021-02-26T16:28:37.273+00:00

    Thank you to both of you karen and cooldad.

    The bottom line is

    If the order in which Skip or Take is returning items is wrong the problem is with the original collection, not the methods.

    The entire list is ok, except for the last 3 numbers. The collection might be the problem.

    Very nice explanation of those methods.

    0 comments No comments