我需要获得两个IEnumerable之间的差异。我为它写了扩展方法。但正如你所看到的,它有性能损失。任何人都可以写出更好的版本吗?
修改
在第一次回复后,我明白我无法解释清楚。我正在三次访问两个阵列。这是性能损失。它必须是一次性的。
PS:两者都是可选的:)
public static class LinqExtensions
{
public static ComparisonResult<T> Compare<T>(this IEnumerable<T> source, IEnumerable<T> target)
{
// Looping three times is performance penalty!
var res = new ComparisonResult<T>
{
OnlySource = source.Except(target),
OnlyTarget = target.Except(source),
Both = source.Intersect(target)
};
return res;
}
}
public class ComparisonResult<T>
{
public IEnumerable<T> OnlySource { get; set; }
public IEnumerable<T> OnlyTarget { get; set; }
public IEnumerable<T> Both { get; set; }
}
答案 0 :(得分:0)
根据用例,这可能更有效:
public static ComparisonResult<T> Compare<T>(this IEnumerable<T> source, IEnumerable<T> target)
{
var both = source.Intersect(target).ToArray();
if (both.Any())
{
return new ComparisonResult<T>
{
OnlySource = source.Except(both),
OnlyTarget = target.Except(both),
Both = both
};
}
else
{
return new ComparisonResult<T>
{
OnlySource = source,
OnlyTarget = target,
Both = both
};
}
}
答案 1 :(得分:0)
您正在寻找一种高效的全外连接。
将所有项目插入Dictionary<TKey, Tuple<TLeft, TRight>>
。如果给定的密钥不存在,请将其添加到字典中。如果存在,请更新该值。如果设置了“左侧成员”,则表示该项目存在于左侧源集合中(您将其称为source
)。正确的成员则相反。你可以在两个集合上使用一次传递来做到这一点。
之后,您遍历此字典的所有值并将相应的项输出到三个集合中的一个,或者您只需将其作为IEnumerable<Tuple<TLeft, TRight>>
返回,这样可以节省对结果集合的需求。