查找两个IEnumerables之间差异的有效方法
本文关键字:有效 方法 之间 IEnumerables 两个 查找 | 更新日期: 2023-09-27 17:53:58
我有
IEnumerable<Tuple<string, string>> allInfo
和IEnumerable<string> info1dim
。如何有效地找出info1dim
与allInfo
的第一阶差?例如:
allInfo = {<"data1", "addinfo1">, <"data2", "addinfo2">, <"data3", "addinfo3">"
和
info1dim = {"data3", "data1", "data4"}
我期望的结果是
{"diff4"}
最有效的方法是什么?我不想运行两个循环。IEnumerables非常大(~100000个元素)
c# HashSet集合有ExceptWith
、UnionWith
和IntersectWith
方法。你想要的可以这样做。
var set1 = new HashSet<string>(allinfo.Select(t => t.Item1));
var set2 = new HashSet<string>(info1dim);
var set1_but_not_set2 = new HashSet<string>(set1);
set1_but_not_set2.ExceptWith(set2);
var set2_but_not_set1 = new HashSet<string>(set2);
set2_but_not_set1.ExceptWith(set1);
但是要小心,HashSet是一个可变集合,这些函数会更改集合。这里有O(n)
操作。构造HashSet对象需要迭代;ExceptWith
操作也是如此。
您可以像这样使用LINQ Except()
:
info1dim.Except(allInfo.Select(i => i.Item1));
注意Except()
在内部使用HashSet<T>
(如这里所述),所以这仍然是O(n)。
也许是这样的?
var diff = info1dim.Where(x => allInfo.Any(c => c.Item1 == x) == false);
如果你将IEnumerable<Tuple<string, string>>
存储在Dictionary<string,string>
中,它会变得快得多!然后你可以写:
Dictionary<string,string> allInfo;
IEnumerable<string> info1dim;
var diff = info1dim.Where(x => allInfo.ContainsKey(x) == false);
在HashSet中加载info1dim并在allInfo中使用Remove foreach item:
// n: size of info1dim ; m: size of allInfo
var diff = new HashSet<string> (info1dim); // O(n)
foreach (var tuple in allInfo) // O(m)
diff.Remove (tuple.Item1); // O(1)
在Ollie回答之前,我不记得ExceptWith
的存在;在源引用验证后,ExceptWith基本上做同样的(foreach -> Remove),所以应该更好;我保持我的代码是尽可能的信息支持