从ObservableCollection中删除键值最有效的方法是什么?

时间:2012-03-31 00:20:54

标签: c# .net linq

我有以下代码从集合中删除组。从技术上讲,应该没有重复,但无论如何它确实会删除所有重复。 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);
                }

            }

1 个答案:

答案 0 :(得分:2)

假设您使用相同的Key和相同的值传递KeyValuePair,这是使用ObseravableCollection的最有效方法。

public void DeleteGroup2(KeyValuePair<int, string> group)
{
    Groups.Remove(group);
}

这是有效的,因为KeyValuePair是一个结构,当应用重载的运算符==时,它正在比较结构的Key和Value数据成员。

如果传入与组obserabableCollection中包含的完全相同的Key和Value,这将会正常工作......如果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,外部Any循环,N代表First,N代表Remove。取外循环乘以内部的总和,得到2N ^ 2

DeleteGroup2是N的BIG O,并且具有所有这些的最佳性能。缺点是您需要知道Key和Value,而不仅仅是Key。它也只会删除它找到的第一个项目。它不会删除具有相同Key和相同值的重复项目。

DeleteGroup3是N + N ^ 2的大B。 N为选择。更糟糕的情况是,你的密钥在那里N次,所以N ^ 2用于删除。

DeleteGroup4是2N的BIG O. N找到索引,在最坏的情况下,如果你有所有具有相同键的项目,则其N将删除它们中的每一个,因为RemoveAtIndex是1的Big O.如果你只知道Key并且你有使用相同密钥的多个项目的可能性。

如果您知道您不会有重复项目,我会使用DeleteGroup2。如果你有可能有重复项,DeleteGroup4应该具有最佳性能。

在旁注中如果没有重复项并且您不一定知道Key和Value,您仍然可以使用DeleteGroup2的最佳性能选项,但创建一个名为KeyValueIntString的类,其属性为Key和Value。然后覆盖IsEquals方法,使其仅比较Key属性,而不是KeyValue结构,它比较Key和Value数据成员。然后,您可以使用ObserableCollection.Remove方法,而不必担心知道存储的值。 I.E.您可以传递具有Key集的KeyValueIntString实例,但您不必担心设置Value属性。

评论后,我决定添加最佳可读性方法,尽管它的性能更差。有N ^ 4的大O. N表示选择,N表示ToList,N表示ForEach,N表示删除。

public void DeleteGroup5(KeyValuePair<int, string> groupToDelete)
{
    (
        from g in Groups
        where g.Key == groupToDelete.Key
        select g
    ).ToList().ForEach(g => Groups.Remove(g));
}