C# 从列表中删除单个项目的最快方法是什么<;T>;在秩序重要的地方没有复制品?

C# 从列表中删除单个项目的最快方法是什么<;T>;在秩序重要的地方没有复制品?,c#,list,indexof,C#,List,Indexof,我有一个项目清单,没有重复的地方顺序的问题 我需要定期从列表中删除一项 一个实际的例子是列表绑定的UI控件,例如允许删除的DataGridView 用户希望按特定顺序查看项目,因此删除后剩余项目应保留其顺序 下面是一些示例代码,似乎表明列表项删除是O(n),因为 (1) 必须通过匹配条件迭代列表以查找要删除的项 (2) List.RemoveAt方法必须向下移动剩余的项 public class Item { public string Name {get; set;} public s

我有一个项目清单,没有重复的地方顺序的问题

我需要定期从列表中删除一项

一个实际的例子是列表绑定的UI控件,例如允许删除的
DataGridView

用户希望按特定顺序查看项目,因此删除后剩余项目应保留其顺序

下面是一些示例代码,似乎表明列表项删除是
O(n)
,因为

(1) 必须通过匹配条件迭代列表以查找要删除的项

(2)
List.RemoveAt
方法必须向下移动剩余的项

public class Item
{
  public string Name {get; set;}
  public string Description {get; set;}
}

public List<Item> Items = new List<Item>();

public void AddItem(string name, string description)
{
  Items.Add(new Item {Name=name, Description=description});
}

public void RemoveItem(string name)
{
  for (int i=0; i<Items.Count; i++)
  {
    if (Items[i].Name == name)
    {
      Items.RemoveAt(i);
      break;
    }
  }
}
公共类项目
{
公共字符串名称{get;set;}
公共字符串说明{get;set;}
}
公共列表项=新列表();
public void AddItem(字符串名称、字符串描述)
{
添加(新项{Name=Name,Description=Description});
}
public void removietem(字符串名称)
{

对于(int i=0;i您不需要循环或自定义方法。请尝试以下操作:

Items.RemoveAll(i => item.Name == name);
编辑

正如@Gian Paolo所评论的,对于
List
数据结构,在最好的情况下,它的复杂性为O(n)如果你想要一个更好的性能,你可以考虑检查其他数据结构,包括“代码> LIKEDLIST < /COD>,<代码>字典<代码>,或者<代码> HasStuts .< /P> < P>一种方法是在你的项上使用一个传统的循环,并移除如果名称匹配的话,

for (int i = Items.Count - 1; i >= 0; i--)
{
    if (Items[i].Name == name)
    {
        Items.RemoveAt(i);
        break;
    }
}

RemoveAt
需要O(n)个时间。因为它必须将项目向左移动,从索引
i
n
items.Count
)。类似于
IndexOf

下面是代码的渐近估计:

public void RemoveItem(string name)
{
  foreach (var item in Items) //n times
  {
    if (item.Name == name)
    {
      Items.RemoveAt(Items.IndexOf(position)); // O(n) + O(n) => O(n)
    }
  }

  // => O(n * n)
}
它在O(n^2)时间内运行

这个代码怎么样

for (int i = Items.Count - 1; i >= 0; i--) // n times
{
    if (Items[i].Name == name)
    {
        Items.RemoveAt(i); //O(n)
    }
}
所以这也在O(n^2)中运行

但是这个代码:

Items.RemoveAll(i => item.Name == name);
在O(n)时间内运行。您应该看到此方法的实现以获得证明。
RemoveAll
对列表中的项目进行一次迭代,如果满足条件,它也会在迭代时开始移位。每个步骤中的移位都是一个赋值,即O(1)。因此整个方法在O(n)时间内运行,比您的实现快得多

更新: 问题现在在删除行后包含一个
中断;

在这种情况下,代码查找项将在找到后停止,并开始删除,这将花费O(n)+O(n)=>O(n)

因此,所讨论的代码与
RemoveAll
之间不会有任何渐近差异


因此,它不会更快,也不能更快,但是
RemoveAll
仍然是一个更干净的代码IMHO。

您不能从正在迭代的集合中删除项,您将获得一个例外,您需要能够使用
项[someNumber]
访问列表?如果是这样,切换到a将使您在删除列表中的任意项时具有更好的性能。删除意味着搜索和删除。数组(列表中的数组)的搜索复杂度为O(n)。如果需要较低的复杂度,则需要另一个数据结构(例如,保留项目名称以快速访问项目的字典)。我需要保留添加到列表中的原始订单项目。我想我可以使用
SortedDictionary
,但这似乎有些过分,会增加开销。为什么
LinkedList
会提高性能?似乎您仍然需要线性扫描,所以它是
O(n)
。是的,是这样,因为这是可行的,而您的解决方案不可行。。(o)即使您的解决方案有效,也会更快,因为额外的
IndexOf
调用会占用大量时间。@BaltoStar这是一种非常干净的删除符合条件的项目的方法。您可能可以更快地实现某些功能,但如果您确实需要一些明显的差异,则意味着您应该寻找不同的解决方案nt数据结构。列表总是需要扫描其中的每一个元素。没有任何alghoritm比这快得多,您将始终具有O(n)复杂性。因此,如果您决定使用列表,请选择最干净的codeagreed cleaner(我知道使用谓词的remove扩展方法)但我问题的精神是performance@BaltoStar,
RemoveAll
实际上是一种
List
的方法,我假设它是非常优化的。你可以检查O(n)+O(n),它是search,remove不是O(n*n)。它仍然是O(n)。是的。n*O(n)是O(n^2)。n代表循环,O(n)代表那一行:)一旦元素被找到,它只被删除一次。没有n个删除过程。这就是为什么你要做一次搜索,这是O(n),你要做一次删除,这又是O(n),总的来说你有O(n)+O(n)。您的困惑可能是因为您遗漏了原始问题中的break运算符。好的,删除后的
break;
只添加了2分钟!。我复制并粘贴了原始问题:)我想迭代的方向无关紧要?找到匹配项的索引是随机的,因此平均值会移动In从0或计数开始的基础数组应相同-1@BaltoStar,是的,
count-1
仅用于迭代目的。不确定,但您的列表将保留顺序,我认为:)