我希望能有效地執行與TakeWhile相同的任務,但回傳兩個序列:
TakeWhile的結果我知道我可以做這樣的事情:
var a = input.TakeWhile(.)。
var b = input.Skip(a.Count)。
但是這似乎有可能是不理想的,取決于容器的型別。我是否錯過了一些在單一操作中實作這一目標的巧妙方法?
我的最終目標是在一個大的集合上進行迭代,而不是對其進行預存盤:
我的最終目標是在一個大的集合上進行迭代,而不是對其進行預存盤。
while(data.count() > 0)
{
var y = data.First().Year。
var year = data.TakeWhile(c => c.year == y);
data = data.Skip(year.Count())。
Console.WriteLine($"{year.Count()}專案在{y}")。
uj5u.com熱心網友回復:
你可以使用ToLookup將原始碼分成兩個結果。
var source = new[ ] { 1, 3, 5, 2, 4, 6。7, 8, 9 }。
Func<int, bool> criteria = x => x % 2 ==1;
bool stillGood = true;
Func<int, bool> takeWhileCriteria = x =>
stillGood = stillGood && criteria(x);
var result = source.ToLookup(takeWhileCriteria)。
var matches = result[true]。
var nonMatches = result[false]。
uj5u.com熱心網友回復:
在一次迭代中分割序列的最簡單的方法是回傳一個每個專案的元組和一個bool是否 "在"。
public static IEnumerable<。 (T Entity, bool IsIn) > MarkWhile<T>(this IEnumerable<T> sequence,
Func<T,bool> predicate)。
{
var isIn = true;
using var etor = sequence.GetEnumerator();
while (etor.MoveNext())
{
var current = etor.Current;
isIn &= predicate(current);
yield return(current, isIn)。
}
這允許你在一個大的集合上進行迭代而不耗盡它,并確定條件何時 "翻轉"。但是你需要一個foreach回圈來一次性完成這個任務。
我們可以創建一個方法,只耗盡序列的 "in "部分,甚至回傳它的計數(當回傳圖元時,我們可以做任何事情),并流化序列的尾部,但我想用一個簡單的foreach來解決。這沒什么不對。另外,可能會有這樣的情況:所有的專案都滿足條件,而你仍然只想回傳有限數量的專案。
uj5u.com熱心網友回復:
你可以創建類似于你想要的東西,但只在非常有限的情況下:
public static class IEnumerableExt {
public static IEnumerable<T> ToIEnumerable<T>(thisIEnumerator<T> e) {
while (e.MoveNext())
yield return e.Current。
}
public static (IEnumerable< T> first, IEnumerable< T> rest) FirstRest<T>(thisIEnumerable< T> src, Func<T,bool> InFirstFn) {
var e = src.GetEnumerator()。
var first = new List<T> ();
while (e.MoveNext() & & InFirstFn(e.Current))
first.Add(e.Current)。
return (first, e.ToIEnumerable() )。)
}
注意,在回傳之前,它必須對first進行迭代和緩沖(如果你試圖在first之前列舉rest怎么辦?修復這些問題將涉及更多的代碼。
我可以在遠處看到某種型別的擴展 LINQ,在那里你傳遞 Actions 和 Funcs 并做一些類似 continuations(IEnumerable的其余部分)的處理,但是我不確定這是否值得。類似于:
public static IEnumerable<。 T> DoWhile<T>(this IEnumerable< T> src, Func<T,bool> whileFn, Action<T> doFn) {
var e = src.GetEnumerator()。
while (e.MoveNext() & & whileFn(e.Current))
doFn(e.Current)。
return e.ToIEnumerable()。
同時你可以使用像:
while (data.Any() ) {
var y = data.First().Year。
var ct = 0;
data = data.DoWhile(d => d.Year == y, d => ct);
Console.WriteLine($"{ct}專案在{y}") 。
最好的答案是停止使用IEnumerable<T>自動列舉,手動列舉:
for(var e = data.GetEnumerator(); e.MoveNext();) {
var y = e.Current.Year。
var ct = 0;
while (e.Current.Year == y)
ct;
Console.WriteLine($"{ct}專案在{y}")。)
一旦你進行手動列舉,你就可以在不損失效率的情況下處理大多數情況下的緩沖,或者針對你的具體需求委托呼叫。
PS: 請注意,針對data.Count()測驗0是非常低效的,你應該始終使用data.Any()。根據data,data.Count()可能永遠不會回傳,或者可能非常昂貴,或者data.Any()可能失去data.First()。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/327600.html
標籤:
