任何類型的運行計數算法需要多個狀態變量:
最接近的事情讓你有Enumerable.Aggregate
,因爲它爲您提供當前值和您選擇輸出的一些自定義每項物品值。在我們的案例中,它可能是以前的價值。
對於簡單的int[]
,您必須爲current run count
增加一些額外的狀態。這將不得不放在您的Linq查詢語句之外。雖然它會起作用,但它與使用for-loop沒有太大區別。
如果不是修改你的枚舉是一個自定義的結構,你可以修改結構也包含運行次數,你可以做一個(有點)更LINQ友好的操作:
class Program
{
class CoinToss
{
public int Value;
public int RunCount;
}
static void Main(string[] args)
{
int[] values = new int[]
{
0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1
};
var coinTosses = values
.Select(v => new CoinToss() { Value = v, RunCount = 1 })
.ToList();
coinTosses.Aggregate(
(previous, current) =>
{
current.RunCount = current.Value == previous.Value
? previous.RunCount + 1
: 1;
return current;
});
foreach (var coinToss in coinTosses)
{
Console.WriteLine("Value: {0}, Run Count: {1}",
coinToss.Value,
coinToss.RunCount);
}
}
}
注Linq手術有副作用有點奇怪,所以這一切都取決於你想要的純潔程度。
在此之後,你可以簡單的選擇:
coinTosses.Where(coinToss => coinToss.RunCount >= 3);
可惜你不能鏈Aggregate
功能,所以你必須建立整個列表這個工作。如果這是一個問題,您應該簡單地使用循環,而不是使用yield return
,因爲您的需求比「查詢」稍微多一點。
+1。優於我的回答,因爲它以通用的方式解決了這個問題,並且不涉及任何奇怪的狀態攻擊(關閉狀態或帶有副作用的linq)。 – 2011-05-31 09:12:41