Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TakeWhile, but get the element that stopped it also

I'd like to use the LINQ TakeWhile function on LINQ to Objects. However, I also need to know the first element that "broke" the function, i.e. the first element where the condition was not true.

Is there a single function to get all of the objects that don't match, plus the first that does?

For example, given the set {1, 2, 3, 4, 5, 6, 7, 8},

mySet.MagicTakeWhile(x => x != 5);

=> {1, 2, 3, 4, 5}

like image 338
David Pfeffer Avatar asked Aug 09 '12 12:08

David Pfeffer


People also ask

What is difference between take and TakeWhile in Linq?

TakeWhile() behaves similarly to the Take() method except that instead of taking the first n elements of a sequence, it "takes" all of the initial elements of a sequence that meet the criteria specified by the predicate, and stops on the first element that doesn't meet the criteria.

What is the difference between Skip () and SkipWhile () extension method?

Skip specifies a number of items to skip. SkipWhile allows you to supply a predicate function to determine how many to skip.

What is the function of the TakeWhile method?

The TakeWhile<TSource>(IEnumerable<TSource>, Func<TSource,Int32,Boolean>) method tests each element of source by using predicate and yields the element if the result is true . Enumeration stops when the predicate function returns false for an element or when source contains no more elements.

How do you use take and skip 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.


2 Answers

I think you can use SkipWhile, and then take the first element.

var elementThatBrokeIt = data.SkipWhile(x => x.SomeThing).Take(1);

UPDATE

If you want a single extension method, you can use the following:

public static IEnumerable<T> MagicTakeWhile<T>(this IEnumerable<T> data, Func<T, bool> predicate) {
    foreach (var item in data) {
        yield return item;
        if (!predicate(item))
            break;
    }
}
like image 101
Maarten Avatar answered Oct 17 '22 10:10

Maarten


LINQ to Objects doesn't have such an operator. But it's straightforward to implement a TakeUntil extension yourself. Here's one such implementation from moreLinq.

like image 43
Ani Avatar answered Oct 17 '22 11:10

Ani