2012-08-09 7 views
14

Chciałbym użyć funkcji LINQ TakeWhile na LINQ do obiektów. Jednak muszę również znać pierwszy element, który "zepsuł" funkcję, tj. Pierwszy element, w którym warunek nie był prawdziwy.TakeWhile, ale otrzymaj element, który zatrzymał to także

Czy istnieje jedna funkcja do uzyskania wszystkich obiektów, które nie pasują, plus pierwsza, która nie pasuje?

Na przykład, biorąc pod uwagę zestaw {1,2,3,4,5,6,7,8},

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

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

+0

można napisać metodę takiego łatwo, ale to nie będzie „leniwe”, ponieważ trzeba znać położenie ostatniego elementu w celu uzyskania następnego. –

+0

[To pytanie] (https://stackoverflow.com/q/2242318/241211) nie jest do końca duplikatem, ale udostępnia [odpowiedź]. (Https://stackoverflow.com/a/6817553/241211) – Michael

Odpowiedz

9

myślę, że można użyć SkipWhile, a następnie pierwszy element.

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

UPDATE

Jeśli chcesz pojedynczą metodę rozszerzenia, można użyć następujących:

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; 
    } 
} 
+1

To wymagałoby wielu połączeń. W takim przypadku mógłbym zrobić "FirstOrDefault". –

+0

+1 za dostarczenie działającego kodu – Gabe

+0

@Maarten, dobra odpowiedź - można zapisać linię, usuwając końcowy "break wydajności"; – allonhadaya

6

LINQ to Objects nie ma takiego operatora. Ale proste jest samodzielne wdrożenie rozszerzenia TakeUntil. Oto one such implementation z moreLinq.

+0

Niestety nie uwzględniają tego w MoreLinq NuGet. Skopiuję i wklejam kod. Dzięki! –

+4

Nazwa '' TakeUntil'' nie przekazuje znaczenia. '' Zdejmij 'jaja z pudełka' 'Dopóki' otrzymasz zły nie znaczy, że bierzesz zły. – bradgonesurfing

+0

@bradgonesurfing TakeUntilInclusive? –

0

Tak dla zabawy:

var a = new[] 
    { 
     "two", 
     "three", 
     "four", 
     "five", 
    }; 
    Func<string, bool> predicate = item => item.StartsWith("t");  
    a.TakeWhile(predicate).Concat(new[] { a.SkipWhile(predicate).FirstOrDefault() }) 
+0

To również ma dwa wywołania funkcji. Możesz również pominąć 'SkipWhile' i przejść od razu do' a.FirstOrDefault (predicate) '. –

Powiązane problemy