Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ continue after Take

Tags:

c#

linq

Say we have an IEnumerable<T> stuff;

Is there a concise way to Take n elements and then another m elements after the first, without re-evaluating?

example code:

stuff.Take(10);
stuff.Skip(10).Take(20); // re-evaluates stuff

What I was thinking was maybe this (not working code)

var it = stuff.GetEnumerator();
it.Take(10);
it.Take(20);

Edit to add to the difficulty and to clarify the complexity of what I would like to accomplish: I want to continue the query after the Take, i.e.

it.Take(10);
var cont = it.Select(Mutate);
cont.Take(20);
cont = cont.Where(Filter);
cont.Take(5);
like image 574
Manuel Schweigert Avatar asked Dec 26 '17 20:12

Manuel Schweigert


People also ask

How to use skip and Take in LINQ?

The Take operator is used to return a given number of elements from an array and the Skip operator skips over a specified number of elements from an array. Skip, skips elements up to a specified position starting from the first element in a sequence.

How to use Take in LINQ?

Take enumerates source and yields elements until count elements have been yielded or source contains no more elements. If count exceeds the number of elements in source , all elements of source are returned. If count is less than or equal to zero, source is not enumerated and an empty IEnumerable<T> is returned.

What is the use of skip in C#?

Use the Skip() method in C# to skip number of elements in an array.

How to use Take in C#?

C# Queryable Take() MethodGet specified number of elements from the beginning using the Take() method. The following is our array. int[] marks = { 35, 72, 50, 90, 95, 85, 52, 67 }; Now, use OrderByDescending to order the elements in Descending order.


1 Answers

You can use the Publish extension method in the System.Interactive NuGet package put out by Microsoft to accomplish this. This is a fantastic library that provides some 'missing' LINQ functions. From the documentation, the Publish method:

Creates a buffer with a view over the source sequence, causing each enumerator to obtain access to the remainder of the sequence from the current index in the buffer.

I.e. it allows you to partially enumerate a sequence and the next time you enumerate the sequence you will pick up where the previous enumeration left off.

var publishedSource = stuff.Publish();

var firstTenItems = publishedSource.Take(10).ToArray();
var nextTwentyTransformedItems = publishedSource.Take(20).Select(Mutate).ToArray();
// How you apply 'Where' depends on what you want to achieve.
// This returns the next 5 items that match the filter but if there are less
// than 5 items that match the filter you could end up enumerating the
// entire remainder of the sequence.
var nextFiveFilteredItems = publishedSource.Where(Filter).Take(5).ToArray(); 
// This enumerates _only_ the next 5 items and yields any that match the filter.
var nextOfFiveItemsThatPassFilter = publishedSource.Take(5).Where(Filter).ToArray()
like image 185
Jason Boyd Avatar answered Oct 11 '22 20:10

Jason Boyd