断言两个List <list <t>&gt;相当于彼此</list <t>

时间:2010-08-17 13:10:41

标签: c# nunit

为了确保两个列表相同,在nunit中,我们可以使用CollectionAssert.AreEquivalent来检查这两个列表是否包含相同的元素(订单不重要)。

但是如何检查两个List<List<T>>是否相同?我们的想法是,如果一个List<T>具有与另一个List<T>相同的元素(再次,顺序并不重要),那么它们是相等的。

5 个答案:

答案 0 :(得分:5)

你必须循环遍历它们以确保它们是等效的,但有一些重要的快捷方式:

  1. 如果它们实际上是同一个实例(在实际代码中经常会出现这种情况),那么ReferenceEquals(x, y)将返回true。否则它不会。如果ReferenceEquals返回true,则它们是等效的。

  2. 如果一个是null而另一个不是,那么显然它们不相等(如果它们都是null,那么你将使用ReferenceEquals捕获上面的那个)。为了安全起见,你还需要测试null,所以在许多情况下你还有另一个捷径。

  3. 如果它们具有不同的大小(对于大多数等效定义,则有例外)它们不相等。立即返回假。

  4. 当您发现不匹配的那一刻,您可以在不继续检查的情况下返回虚假。

  5. 如果它们已经排序,那么比较它们会更快。如果您可以对它们进行排序,或者无法跟踪它们是否已排序,然后仅在需要时进行排序,则可以大大加快速度。 (请注意,当不必要地对已经排序的列表进行排序时,许多排序算法会出现更糟糕的行为。)

答案 1 :(得分:2)

这是一次未经测试的尝试。如果每个内部列表包含m个元素,并且外部列表列表包含n个列表,我相信复杂性为O (n^2 x m),但我可能错了。 假设:

  1. T未实现IComparable或任何允许排序的界面。
  2. 排序与List<List<T>>和撰写List<T>对象的相等无关。
  3. -

    public static bool ListListsAreEqual<T>(List<List<T>> listlist1, List<List<T>> listlist2)
    {
        if (listlist1.Count != listlist2.Count)
            return false;
    
        var listList2Clone = listlist2.ToList();
    
        foreach (var list1 in listlist1)
        {
            var indexOfMatchInList2 = listList2Clone
                       .FindIndex(list2 => ListsArePermutations(list1, list2));
    
            if (indexOfMatchInList2 == -1)
                return false;
    
            listList2Clone.RemoveAt(indexOfMatchInList2);
        }
    
        return true;
    }
    
    private static bool ListsArePermutations<T>(List<T> list1, List<T> list2)
    {
        return list1.Count == list2.Count && new HashSet<T>(list1).SetEquals(list2);
    }
    

答案 2 :(得分:0)

我认为你不会单独检查每个元素。 我通常会首先检查相等的长度,然后在列表长度上循环说出i并检查list1 [i] == list2 [i]

<强>更新

抱歉,错过了(中心)部分关于不必按顺序排列的元素。在这种情况下,使用第二个列表的元素创建一个HashSet,并检查list1中的每个元素(如果它在hashset中)。这样可以将查找的运行时间从线性减少到对数。

更新2 如Donald Ray所述,如果任何列表中可能出现多个单个对象,则必须检查两种方式。

答案 3 :(得分:0)

我认为您需要编写自己的代码才能执行此操作。

看看CollectionAssert.AreEquivalent如何与Reflector一起使用,然后编写自己的帮助类“MyAsserts”。

如果你希望比O(n ^ 2 * m ^ 2)跑得更快,那么你必须要聪明,其中 n 是最外面列表中的列表数量, m < / em>是内部列表中的项目数。

简单的解决方案是遍历list1中的所有“内部列表”,并使用CollectionAssert.AreEquivalent中的代码来检查list2是否包含这样的列表。然后交换list1和list2并重复。但是你可以做得更好。

(然后,当列表不相同时,您需要弄清楚如何生成有用的消息。)

答案 4 :(得分:-1)

我会使用SelectMany()并将列表展平。现在,您可以使用Assert.Equals()将元素与元素进行比较,或者对列表使用常规集合断言。带有两个from子句的查询表达式将执行相同的操作:

void AssertEquals<T>(List<List<T>> expected, List<List<T>> actual)
{
  var flatExpected = expected.SelectMany(x=>x);
  var flatActual = expected.SelectMany(x=>x);

  CollectionAssert.Equals(flatExpected, flatActual);
}

请注意,这只是一个非常天真的实现,扁平序列可能相等,而源序列包含相同的元素,但在不同的分区中。