我有两个List<T>
个对象(其中T
对于两个对象都是相同的类型),我需要能够确定它们是否包含相同的值集,即使值不是& #39; t按相同顺序排列。
对象是否有任何内置机制来完成此任务,或者我是否需要编写自己的算法?
或许,我应该使用不同类型的集合,而不是List<T>
?
如果我要编写自己的算法,它可能包含以下步骤 - 如果我走这条路线,我会尝试在最终版本中对其进行优化:
我知道这有一些注意事项,例如T必须具有可比性 - 我现在使用默认比较(例如.Equals()
),并为通用类型定义了适当的约束
答案 0 :(得分:1)
根据可用信息,我怀疑支持重复的最有效解决方案是
请注意,我假设在此操作期间有足够的内存可用于创建列表的排序副本(应该要求保存是必需的)。
答案 1 :(得分:1)
所以我们从一个简单的SetEquals
开始,然后从那里开始。 HashSet
已经有了这样一个方法的实现,它可以比较两个集合的相等性,所以我们可以创建一个包装器,以便我们可以将它用于任何类型的序列:
public static bool SetEquals<T>(this IEnumerable<T> first, IEnumerable<T> second,
IEqualityComparer<T> comparer = null)
{
return new HashSet<T>(second, comparer ?? EqualityComparer<T>.Default)
.SetEquals(first);
}
接下来,为了说明你有一个包,而不是一个集合,我们可以只取你拥有的两个序列,对它们进行分组,并将其投影到一个包含项目的对中,以及匹配项目。如果我们为两个集合执行此操作,那么我们可以将这些对象序列比较为,并查看它们是否设置为相等。如果密钥计数对序列都设置为相等,那么原始序列是相同的:
public static bool BagEquals<T>(
this IEnumerable<T> first,
IEnumerable<T> second)
{
Func<IEnumerable<T>, IEnumerable<KeyValuePair<T, int>>> groupItems =
sequence => sequence.GroupBy(item => item,
(key, items) => new KeyValuePair<T, int>(key, items.Count()));
return groupItems(first)
.SetEquals(groupItems(second));
}
答案 2 :(得分:1)
这是CollectionAssert.AreEquivalent
的重新实现(参考代码用DotPeek反编译)但是它不是抛出异常而是返回一个bool。
inner.xsd