问题描述
我有两个 List<T>
对象(其中 T
是两个对象的相同类型),我需要能够确定它们是否包含相同的一组值,即使这些值的顺序不同.
I have two List<T>
objects (where T
is the same type for both objects), and I need to be able to determine whether they contain the same set of values, even if the values aren't in the same order.
对象是否有任何内置机制来实现这一点,还是我需要编写自己的算法?
Do the objects have any built-in mechanisms to accomplish this, or do I need to write my own algorithm?
或者,我应该使用不同类型的集合,而不是 List<T>
?
Or perhaps, should I be using a different type of collection, rather than List<T>
?
如果我要编写自己的算法,它可能包括以下步骤 - 如果我走这条路,我将尝试在最终版本中优化它:
If I were to write my own algorithm, it would probably consist of the following steps - I'll try to optimize this in the final version, if I go this route:
- 这两个集合是否包含相同数量的值?如果不返回 false.
- 计算每个值在每个集合中出现的次数,如果计数不相等则返回 false.
- 如果我在两个集合的末尾没有任何值计数不等,则返回 true.
我知道对此有一些警告,例如 T 必须具有可比性这一事实 - 我现在使用默认比较(例如 .Equals()
)并定义了适当的约束对于泛型类型.
I know there are some caveats to this, such as the fact that T has to be comparable - I'm using the default comparison for now (e.g. .Equals()
) with appropriate constraints defined for the generic type.
推荐答案
这里是 CollectionAssert.AreEquivalent
(参考代码是用 DotPeek 反编译的)但是它不会抛出异常,而是返回一个布尔值.
Here is a reimplementation of CollectionAssert.AreEquivalent
(reference code was decompiled with DotPeek) however instead of throwing a exception it returns a bool.
public class CollectionMethods
{
public static bool AreEquivalent(ICollection expected, ICollection actual)
{
//We can do a few quick tests we can do to get a easy true or easy false.
//Is one collection null and one not?
if (Object.ReferenceEquals(expected, null) != Object.ReferenceEquals(actual, null))
return false;
//Do they both point at the same object?
if (Object.ReferenceEquals(expected, actual))
return true;
//Do they have diffrent counts?
if (expected.Count != actual.Count)
return false;
//Do we have two empty collections?
if (expected.Count == 0)
return true;
//Ran out of easy tests, now have to do the slow work.
int nullCount1;
Dictionary<object, int> elementCounts1 = CollectionMethods.GetElementCounts(expected, out nullCount1);
int nullCount2;
Dictionary<object, int> elementCounts2 = CollectionMethods.GetElementCounts(actual, out nullCount2);
//One last quick check, do the two collections have the same number of null elements?
if (nullCount2 != nullCount1)
{
return false;
}
//Check for each element and see if we see them the same number of times in both collections.
foreach (KeyValuePair<object,int> kvp in elementCounts1)
{
int expectedCount = kvp.Value;
int actualCount;
elementCounts2.TryGetValue(key, out actualCount);
if (expectedCount != actualCount)
{
return false;
}
}
return true;
}
private static Dictionary<object, int> GetElementCounts(ICollection collection, out int nullCount)
{
Dictionary<object, int> dictionary = new Dictionary<object, int>();
nullCount = 0;
foreach (object key in (IEnumerable)collection)
{
if (key == null)
{
++nullCount;
}
else
{
int num;
dictionary.TryGetValue(key, out num);
++num;
dictionary[key] = num;
}
}
return dictionary;
}
}
这篇关于确定两个 List<T> 是否存在的最佳方法是什么?对象包含相同的值集,即使它们的顺序不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!