从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);
                }
            }

从ObservableCollection中移除KeyValue是最有效的方法

假设您传入具有相同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));
}