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