我正在寻找一种高效的方法,将第二个ICollection的不同项添加到现有ICollection中。我正在使用.NET 4。
答案 0 :(得分:13)
这应该这样做:
list1.Union(list2).Distinct(aCustomComparer).ToList()
答案 1 :(得分:6)
只要它们是IEnumerable,你就可以使用Linq的回答:
var union = firstCollection.Union(secondCollection);
这将使用默认的相等比较,对于大多数对象,它是参照相等。要更改此设置,您可以为集合中的项类型定义一个IEqualityComparer泛型,它将执行更多的语义比较,并将其指定为Union的第二个参数。
答案 2 :(得分:2)
添加到现有列表的另一种方法是:
list1.AddRange(list2.Distinct().Except(list1));
答案 3 :(得分:2)
您问题的最直接答案 - 因为您没有提供有关ICollection的实际类型的详细信息,您输入或需要作为输出是由KeithS给出的
var union = firstCollection.Union(secondCollection);
这将返回一个独特的IEnumerable - 如果这是你需要的那么它非常快。我做了一个小测试应用程序(下面),它针对重复数据删除的简单hashset方法运行union方法(MethodA)并返回一个Hashset<>(MethodB)。联合方法DESTROYS hashset:
方法A:1毫秒
方法B:2827ms
但是 - 必须将IEnumerable转换为其他类型的集合,例如List<> (就像ADas发布的版本一样)改变了一切:
只需将.ToList()添加到MethodA
即可var union = firstCollection.Union(secondCollection).ToList();
更改结果:
方法A:3656ms
方法B:2803毫秒
所以 - 似乎需要了解您正在使用的具体案例 - 并且应该测试您提出的任何解决方案 - 因为小的(代码)更改可能会产生巨大的影响。
下面是我用来比较这些方法的测试 - 我确定这是一种愚蠢的测试方法 - 但它似乎有效:)
private static void Main(string[] args)
{
ICollection<string> collectionA = new List<string>();
ICollection<string> collectionB = new List<string>();
for (int i = 0; i < 1000; i++)
{
string randomString = Path.GetRandomFileName();
collectionA.Add(randomString);
collectionA.Add(randomString);
collectionB.Add(randomString);
collectionB.Add(randomString);
}
Stopwatch testA = new Stopwatch();
testA.Start();
MethodA(collectionA, collectionB);
testA.Stop();
Stopwatch testB = new Stopwatch();
testB.Start();
MethodB(collectionA, collectionB);
testB.Stop();
Console.WriteLine("MethodA: {0}ms", testA.ElapsedMilliseconds);
Console.WriteLine("MethodB: {0}ms", testB.ElapsedMilliseconds);
Console.ReadLine();
}
private static void MethodA(ICollection<string> collectionA, ICollection<string> collectionB)
{
for (int i = 0; i < 10000; i++)
{
var result = collectionA.Union(collectionB);
}
}
private static void MethodB(ICollection<string> collectionA, ICollection<string> collectionB)
{
for (int i = 0; i < 10000; i++)
{
var result = new HashSet<string>(collectionA);
foreach (string s in collectionB)
{
result.Add(s);
}
}
}