假设我们有一个List集合A和一个int数组B.现在我们需要看到,无论顺序如何,数组B中的哪些元素存在于集合A中。添加缺少的元素和删除在数组B中找不到的元素。
我使用以下代码完成了这项工作:
for (int i = 0; i < A.Count; i++)
{
for (int k = 0; k < B.Length; k++)
{
if (A[i] == B[k]) goto Found;
}
A.RemoveAt(i);
Found: continue;
}
for (int i = 0; i < B.Length; i++)
{
for (int k = 0; k < A.Count; k++)
{
if (A[k] == B[i]) goto Found;
}
A.Add(B[i]);
Found: continue;
}
是否有更快的方法来达到相同的效果?请注意,我不能只删除A并根据B创建一个新的,因为这只是一个简化的例子。
答案 0 :(得分:1)
非常短(而且相当快)的版本将是
A.Clear();
A.AddRange(B);
但也许你真的不想那样。但是,使用Contains
方法时,您可以稍微缩短代码:
for (int i = A.Count; i >= 0; i--) {
if (!B.Contains(A[i])) {
A.RemoveAt(i);
}
}
foreach (var item in B) {
if (!A.Contains(item)) {
A.Add(item);
}
}
第一个循环不能是foreach
循环,因为A
在迭代时被修改。它也向后运行以确保查看每个项目。
然而,这具有二次运行时间(更准确地说: O (| A |·| B |))并且可以使用大型列表相当快地(不是意图)加速。为了获得更好的运行时间(尽管存储器要求更高),您可能需要将HashSet
用于仅需要 O (| A | + | B |)运行时性能的Contains
测试 O (| A | + | B |)更多内存的成本。
这是一个相当冗长的方式,但是:如果您不关心商品的订单,那么您的列表似乎更像是套装。在这种情况下,设置数据结构更有意义,因为它可以有效地执行这些操作。你显然不关心元素顺序,因为你最后只是在最后添加了缺失的项目。
答案 1 :(得分:1)
我认为使用LINQ应该很快:
A.RemoveAll(tmp => !B.Contains(tmp));
A.AddRange(B.Where(tmp => !A.Contains(tmp)));
编辑:正如乔伊所指出的,这仍然只是O(| A |·| B |)。
答案 2 :(得分:1)
这是徒劳的,最终你会再次收集B集合。只需创建基于数组B的集合A.这很简单!
答案 3 :(得分:0)
好的,我会再给你一些细节。我在上面设置的示例过于简单了。我实际拥有的是一个加载在XElement上的XML文件。有些子节点具有特定属性,可以精确映射到应用程序中自定义类型的属性。每个子节点都创建一个上述类型的实例。
出于可扩展性的目的,如果我需要向自定义类型添加新属性,我希望使用具有空值的new属性更新XML文件中的所有记录。如果我删除一个属性,我想要相反。所以在这里,我必须检查自定义类型的PropertyInfo []的属性集合。我无法删除所有属性并再次重新创建它们,因为它们的值也会丢失。
在我的方法中,我可以看到一些检查已经完成了两次,因为我真的是新手,我认为这可能是一个偶然的问题,这是一个我想不到的方式。谢谢大家的好评。