簡體   English   中英

遍歷集合並對其進行修改的最佳實踐?

[英]Best practice for iterating over a collection and modifying it?

我正在嘗試遍歷一組項目,執行一個操作,然后在當前索引處刪除該項目。

我目前已實現的方式如下:

foreach (CormantRadPane pane in GetPanes().ToList())
{
    pane.Clear();
    StateManager.Remove(pane);
    LayoutManager.Instance.RegisteredPanes.Remove(pane);
    Items.Remove(pane);
}

通過調用ToList,我創建了該集合的副本,但維護了對第一個集合中每個對象的引用。 這使我可以遍歷GetPanes的集合返回,而無需“技術上”修改集合。

顯然,這很容易導致一些很難發現的錯誤。 以一種干凈的方式執行這種邏輯的標准方法是什么,但是對於所發生事情的復雜性,這還更加清楚嗎?

我環顧四周,看到了諸如使用for循環並向后瀏覽列表的事情,但這似乎實在是太龐大了。 我的感覺與保留第二個項目列表“刪除”大致相同,然后在第一個循環完成后遍歷該列表,刪除在第二個列表中找到的每個對象。

您如何處理? 謝謝。

除了使用當前方法,您還可以創建一個變量並使用它,我建議使用for循環進行窗格刪除,技巧只是反向進行迭代:

var panes = GetPanes();
int count = panes.Count;
for(int i= count - 1; i>=0; i--)
{
       pane = panes[i];
       pane.Clear();
       StateManager.Remove(pane);
       LayoutManager.Instance.RegisteredPanes.Remove(pane);
       //Items.Remove(pane);
       Items.RemoveAt(i);
} 

調用Items.Remove(pane); 取O(n)(如果為列表),但使用Items.RemoveAt(i); 它需要O(1),所以您當前的方法需要O(n ^ 2),但是如果您可以調用RemoveAt(index)(您有一些列表並且它們以相同的方式排序),則可以在O(n)中進行處理。

您可以使用linq列表擴展名,例如:

List<Item> items = GetItems(); items.ForEach(i => {i.DoStuff();i.DoStuff2(););}

至少那是我通常要做的。

您所指的是一個Robust Iterator但是我不認為C#和Java中提供的迭代器都是健壯的。

如果只想穩健地遍歷List ,則可以通過跟蹤列表的索引來實現自己的Robust Iterator。 對於具有較少定義順序的集合以及某些非隨機訪問可迭代項(例如數據庫結果集),這可能不起作用。

也許另一個回答者可以幫助您找到一種在特定情況下不需要強大的迭代器的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM