从ObservableCollection中移除KeyValue是最有效的方法
本文关键字:有效 方法 KeyValue ObservableCollection | 更新日期: 2023-09-27 18:29:31
我有以下代码从集合中删除组。从技术上讲,不应该有重复,但它确实删除了所有内容。LINQ对.Remove.Where..
有什么诀窍吗?
public void DeleteGroup(KeyValuePair<int, string> group)
{
while (this.Groups.Any(g => g.Key.Equals(group.Key)))
{
var groupToRemove = this.Groups.First(g => g.Key.Equals(group.Key));
this.Groups.Remove(groupToRemove);
}
}
假设您传入具有相同Key和相同Value的KeyValuePair,这是OberableCollection最有效的方法。
public void DeleteGroup2(KeyValuePair<int, string> group)
{
Groups.Remove(group);
}
这是因为KeyValuePair是一个结构,当应用重载运算符==时,它将比较结构的Key和Value数据成员。
同样,如果您传入Groups observableCollection中包含的完全相同的Key和Value,这将非常有效。。。如果值不匹配,它将不起作用。
在幕后,ObserableCollection基本上是一个列表,因此它必须迭代执行==运算符的每个项。您发布的代码也是如此。仅仅因为它使用LINQ并不意味着它的效率会更高。它不像LINQ where子句那样使用任何索引,就像LINQ to SQL一样。
public void DeleteGroup3(KeyValuePair<int, string> groupToDelete)
{
var itemsToDelete =
(
from g in Groups
where g.Key == groupToDelete.Key
select g
);
foreach (var kv in itemsToDelete)
{
Groups.Remove(kv);
}
}
如果您想保证删除所有项目,甚至是那些具有重复键的项目,那么这可能是使用linq最有效的方法。
public void DeleteGroup4(KeyValuePair<int, string> group)
{
List<int> keyIndexes = new List<int>();
int maxIndex = Groups.Count;
for (int i = 0; i < maxIndex; i++)
{
if (Groups[i].Key == group.Key)
{
keyIndexes.Add(i);
}
}
int indexOffset = 0;
foreach (int index in keyIndexes)
{
Groups.RemoveAt(index - indexOffset);
indexOffset++;
}
}
如果您有多个具有相同密钥的项,或者您不知道与原始项完全相同的键值对,那么这应该是所有项中性能最好的。
我相信你的DeleteGroup方法是2N^2…N的BIG O,用于外部Anywhile循环,N用于First,N用于Remove。取外循环乘以内循环之和,得到2N^2
DeleteGroup2是N中的大人物,在所有人中表现最好。缺点是您需要同时知道Key和Value,而不仅仅是Key。它也只会删除它找到的第一个项目。它不会删除具有相同Key和相同Value的重复项目。
DeleteGroup3是N+N^2的大O。N表示选择。更糟糕的情况是,你的钥匙在那里N次,所以N^2次删除。
DeleteGroup4是2N的大O。N来查找索引,在最坏的情况下,如果所有项都具有相同的键,则删除每个项的N,因为RemoveAtIndex是1的大O。如果您只知道密钥,并且您有可能拥有多个具有相同密钥的项目,则这将具有最佳性能。
如果你知道你不会有重复的项目,我会使用DeleteGroup2。如果您有可能有重复,DeleteGroup4应该具有最佳性能。
顺便说一句,如果没有重复项,并且您不一定同时知道Key和Value,您仍然可以使用DeleteGroup2的最佳性能选项,但可以创建一个名为KeyValueIntString的类,该类的属性为Key和Value。然后覆盖IsEquals方法,使其只比较Key属性,而不是同时比较Key和Value数据成员的KeyValue结构。然后您可以使用ObserableCollection.Remove方法,而不必担心知道存储的值。也就是说,您可以传入设置了Key的KeyValueIntString的实例,但不必担心设置Value属性。
在评论之后,我决定添加可读性最好的方法,尽管它的性能确实较差。具有N^4的大O。N表示select,N表示ToList,N表示ForEach,N表示Remove。
public void DeleteGroup5(KeyValuePair<int, string> groupToDelete)
{
(
from g in Groups
where g.Key == groupToDelete.Key
select g
).ToList().ForEach(g => Groups.Remove(g));
}