C# 从列表中删除单个项目的最快方法是什么<;T>;在秩序重要的地方没有复制品?
我有一个项目清单,没有重复的地方顺序的问题 我需要定期从列表中删除一项 一个实际的例子是列表绑定的UI控件,例如允许删除的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
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
仅用于迭代目的。不确定,但您的列表将保留顺序,我认为:)