2015-05-14 123 views
-3

從0循環到列表的末尾(列表或地圖)以及從末端循環到0的場景,有哪些場景?以下是從0到最後遍歷列表的代碼片段,以篩選出一些特定的學生名稱。這段代碼是否會在任何情況下拋出異常?從列表末尾迭代到零對這段代碼有什麼影響嗎?何時從0循環到結束以及何時從結束循環到0?

List<Dictionary<string, string>> allStudentsList = allStudentsArray.ToList(); 
for (int i = 0; i < allStudentsList .Count-1; i++) { 
    Dictionary<string, string> student= allStudentsList .ElementAt(i); 
    string studentName; 
    bool hasValue = studentName.TryGetValue("id", out studentName); 
    if (hasValue) { 
     if (studentName.StartsWith("John") { 
      allStudentsList.RemoveAt(i); 
      i--; 
     } 
    } 
} 
+0

把它作爲評論,因爲它與你的問題沒有關係,但你應該用列表中的索引代替elementat(i)。ElementAt是一個linq運算符,因此它或者爲列表進行了優化(並且只是添加了一個方法開銷),要麼它沒有列表特定的路徑,然後導致巨大的減速,因爲它需要每次迭代整個列表直到查找元素的索引。 –

回答

1

首先,您的問題包含語義錯誤。它是:

end-1到包括0

如果你開始end,你會立即收到一條ArgumentOutOfRangeException因爲ElementAt方法規範。

如果從移動從右到左,你不必執行情況的增量(i++)的hasValue是真實的。只是因爲索引左側的項目沒有移位。因此,您可以將其實現爲:

List<Dictionary<string, string>> allStudentsList = allStudentsArray.ToList(); 
for (int i = allStudentsList.Count-1; i >= 0; i--) { 
    Dictionary<string, string> student = allStudentsList.ElementAt(i); 
    string studentName; 
    bool hasValue = studentName.TryGetValue("id", out studentName); 
    if (hasValue) { 
     if (studentName.StartsWith("John") { 
      allStudentsList.RemoveAt(i); 
     } 
    } 
} 

接下來它可以使性能有所不同。如果您從List<T>.RemoveAt中刪除元素,則表示索引右側的所有元素都放置在左側一個位置。現在,如果您首先從右側移除,則右側的項目數量會很小,而且如果索引位於零附近,則要移到左側的項目數量會更小(僅因爲某些元素已經去除)。但是,如果hasValue只很少是true,那麼不要期待性能提升。

在這種情況下,for是向前還是向後完成並不重要,因爲在不同迭代中存在「共享狀態」。

+2

我不同意你的前兩段,你說OP的「問題包含語義錯誤」。 OP使用單詞「end」來描述列表的結尾,而不是作爲索引變量。具體來說,OP兩次表示「列表結束」,所以很明顯他(或她)沒有使用「結束」作爲索引。所以說,它應該是「結束 - 1」就像說「這列火車走到最後 - 軌道1」。 – RenniePet

1

現在,我想提供一個同伴答案CommuSoft的最優秀和徹底的事先評論。 (即 「不相關」,而是: 「並行.. tangental .. '僅供參考' ......」)*

一般(和不管()所使用的語言的! ...),如果你正在迭代通過任何排序你從哪個數據結構刪除事情,你總是想要迭代「從結尾到0」。 (否則,真的沒關係......)

爲什麼?因爲任何時候你從任何一種收藏品中刪除任何東西,那麼這個收藏集的'長度'就會減少1. 如果是你從後到前迭代,這不是一個問題:你永遠不會「錯過任何東西」,你也不會「兩次遇到同樣的元素。」如果你以另一種方式旅行,兩個(!)都是非常真實的(所以「完全可以避免」)。

+0

小評論:對於*鏈表*,它不完全正確,向後迭代將導致* O(n^2)*,而向前迭代產生* O(n)*時間複雜度。一些迭代器/枚舉提供刪除功能,在這種情況下,可以做內聯刪除... –

+1

我不完全確定你的結論是什麼邏輯「迭代鏈接列表向前*與反向」產生任何差異完全是O-cost。 (儘管如此,我慷慨地承認你的觀點,沒有進一步的評論,「毫無疑問,是真的」。)我的評論的確具體針對那些「一個人在收藏中的現狀」由「 *順序,*不是(與「鏈接列表」的情況完全相同)「指針」。因此,我認爲我們各自的有效評論之間沒有衝突。 –