簡體   English   中英

從列表中刪除元素最有效的方法是什么 <T> 在C#中同時進行foreach嗎?

[英]what is the most performant way to delete elements from a List<T> in c# while doing a foreach?

我想知道做foreach時從c#中的列表中刪除元素的最佳方法是什么。

這是一個代碼示例。 首先,我創建一個包含一些元素的列表,然后刪除一個元素:

List<int> foo = new List<int>();
foo.Add(1);
foo.Add(2);
foo.Add(3);
foreach (int i in foo)
{
    if (i==2)
    {
        foo.Remove(i);
    }
}

當我運行它時,我得到一個InvalidOperationException但是如何用一種高性能的方法來解決呢?

如果必須在枚舉時刪除條目,請向后移動列表,然后刪除需要刪除的項目。

for (var i = foo.Count-1 ; i >= 0 ; i--) {
    if (MustBeRemoved(foo[i])) {
        foo.RemoveAt(i);
    }
}

請注意,這不是在您的文章,您知道需要刪除的值的情況下需要。

foo.RemoveAll(x => x == 2);

如果您決定不使用for和foreach;)

我認為您的實際用例比您所計划的要復雜。 因此,假設您實際上有一些條件適用於每個元素並且多個元素可以滿足。 我們稱其為謂詞

List<T>公開允許您提供謂詞的RemoveAll方法。 然后刪除與該謂詞匹配的所有項目。 例如

Func<int, bool> isEven = i => i % 2 == 0;
List<int> ints = ...
ints.RemoveAll(item => isEven(item));
// ints will only contain odd numbers 

要考慮的其他方法是在for循環中向后遍歷該列表並按索引刪除,構建包含要刪除項目的第二個列表,然后在第二個列表的第二個循環 ,從第一個列表中刪除項目。 或者,您可以編寫查詢以構造一個包含要保留的項目的序列。

為什么需要循環?

foo.Remove(2);

我認為最好的方法是使用簡單的for循環向后迭代。

for(int i = foo.Count-1; i>=0; i--)
    if(foo[i]==2) foo.RemoveAt(i);

如下更改您的foreach

foreach (int i in new List<int>(foo))

如果要刪除任意元素,而不僅僅是一個,可以使用RemoveAll並指定一個謂詞:

foo.RemoveAll(element => (element == 2));

您可以將要刪除的項目添加到臨時列表,然后在循環后將其刪除:

List<int> foo = new List<int>();
foo.Add(1);
foo.Add(2);
foo.Add(3);

List<int> remove = new List<int>();

foreach (int i in foo) {
  if (i==2) {
    remove.Add(i);
  }
}

foreach (int i in remove) {
  foo.Remove(i);
}

迭代時無法編輯列表。

考慮:

List<int> foo;
int[] bar = foo.ToArray();

foreach(int i in bar)
{
    if (i == 2)
    {
        foo.Remove(i);
    }
}

但是要當心:您應該向后移動此列表,因為從foo列表中刪除某個項目將意味着該酒吧列表不再與其對齊。 (如果您不后退,則必須跟蹤刪除次數並調整傳遞給remove調用的索引!)

暫無
暫無

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

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