找到2个IEnumebles之间差异的有效方法

时间:2015-06-07 23:22:03

标签: c# ienumerable

我有

IEnumerable<Tuple<string, string>> allInfo

IEnumerable<string> info1dim。有效找到info1dimallInfo的第一个暗点之间的差异的方法是什么?例如:

allInfo = {<"data1", "addinfo1">, <"data2", "addinfo2">, <"data3", "addinfo3">"

info1dim = {"data3", "data1", "data4"}

我期望的结果是

{"diff4"}

最有效的方法是什么? 我不想运行两个循环。 IEnumerables是巨大的(~100000元素)

4 个答案:

答案 0 :(得分:4)

C#HashSet集合包含ExceptWithUnionWithIntersectWith方法。你想要的就是这样。

        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操作也是如此。

答案 1 :(得分:2)

您可以像这样使用LINQ Except()

info1dim.Except(allInfo.Select(i => i.Item1));

请注意Except()在内部使用HashSet<T>(如here所述),所以这仍然是O(n)。

答案 2 :(得分:1)

也许是这样的?

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);

答案 3 :(得分:0)

将您的info1dim加载到HashSet中,并在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的存在;在source reference验证后,基本上做同样的事情(foreach - &gt;删除),所以应该更好;我将我的代码保留为信息丰富的支持