[英]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.