2011-08-02 102 views
0

我想計算System.Collections.Generic.LinkedList中的起始節點和終止節點之間的節點總數,類似於STL算法std: :在C++中計數爲(除了我打算在計數中包含末端節點)。C#:計算LinkedList中節點之間的元素數

我還沒有弄清楚例如如何使用任何LINQ擴展方法有效地計算出這個數字,所以我已經實現了這樣的計數器(不包括所有和一致性檢查):

var counter = 1; 
var node = iStartNode; 
while (!ReferenceEquals(node, iEndNode)) 
{ 
    node = node.Next; 
    ++counter; 
} 

但必須有一個更有效的解決方案,千萬不能」那裏?任何建議,高度讚賞。

+0

爲什麼你認爲應該有更高效的解決方案? –

+0

我可能應該使用_compact_而不是_efficient_。從性能角度來看,上面的解決方案可以嗎? –

+0

從性能角度來看,沒關係。如果您很高興有一些擴展方法可能對別處有所幫助,請參閱我的答案以獲得更緊湊的代表性。 –

回答

6

我相信你的解決方案是最高效和最可讀的。即使你可以在LINQ中找到一個實現,它肯定會是曲折的。

通過排除null檢查我認爲你的意思是說,真正的代碼不會拋出node運行在列表末尾。

+0

感謝大衛的回答。實際上,我已經實現了我的方法,以便在列表末尾運行時拋出,但是以受控方式運行。我驗證了開始和結束節點都包含在同一個鏈接列表中,並且開始節點出現在結束節點之前。但這可能是一個不同的故事... –

4

我能想到的唯一的辦法可能是略有清潔 - 或者至少,讓一般的代碼鏈表工作節點稍微乾淨 - 將寫兩個擴展方法:

static IEnumerable<LinkedListNode<T>> AsEnumerable<T> 
    (this LinkedListNode<T> node) 
{ 
    // Can even call list.Head.AsEnumerable() when the list is empty! 
    while (node != null) 
    { 
     yield return node; 
     node = node.Next; 
    } 
} 

static IEnumerable<LinkedListNode<T>> ReverseEnumerable<T> 
    (this LinkedListNode<T> node) 
{ 
    while (node != null) 
    { 
     yield return node; 
     node = node.Previous; 
    } 
} 

然後你可以使用LINQ:

var count = node.AsEnumerable().TakeWhile(x => x != endNode).Count(); 

這將不包括本身endNode,所以你可能想通過1遞增它(這將是不錯的TakeUntilSkipUntil方法,其中像TakeWhileSkipWhile,但包括第一位的謂詞不匹配的節點作爲最後一個採取或跳過。)

注意,這不會去爆炸,如果它未能找到endNode - 它只會從開始節點開始計算列表的數量。

關於擴展方法的好處是它們基本上讓你在列表中作爲一個序列在任何點上進行操作。

+0

感謝喬恩這個有趣的答案。我看不到你實際上使用了ReverseEnumerable方法,你是否僅僅爲了完整而包含它?我絕對同意你對TakeUntil/SkipUntil方法的評論;我最初在框架中尋找類似的東西,但由於找不到任何東西,我回到了上面概述的解決方案。 –

+0

@Anders:絕對如此。考慮到你有一個雙鏈表,我不會在沒有第二個的情況下放入第一個擴展方法:) –

+0

對於我所見過的最不「曲折」的Linq查詢之一,+1! ;-) –

相關問題