如何断言两个列表在Python中包含相同的元素?

sat*_*oru 138 python unit-testing

在编写测试用例时,我经常需要声明两个列表包含相同的元素而不考虑它们的顺序.

我一直在将列表转换为集合.

有没有更简单的方法来做到这一点?

编辑:

正如@MarkDickinson指出的那样,我可以使用TestCase.assertItemsEqual.

TestCase.assertItemsEqualPython2.7中的新增注释.如果您使用的是旧版本的Python,则可以使用unittest2 - Python 2.7新功能的后端.

fla*_*ini 117

从Python 3.2开始unittest.TestCase.assertItemsEqual,doc(doc)已被替换为unittest.TestCase.assertCountEqual(doc),它正是您正在寻找的,正如您可以从python 标准库文档中读取的那样.该方法有点误导性地命名,但它完全符合您的要求.

a和b具有相同数字的相同元素,无论它们的顺序如何

这是一个简单的例子,它比较具有相同元素但顺序不同的两个列表.

  • 使用assertCountEqual测试将成功
  • assertListEqual由于两个列表的顺序不同,使用测试将失败

这是一个小例子脚本.

import unittest


class TestListElements(unittest.TestCase):
    def setUp(self):
        self.expected = ['foo', 'bar', 'baz']
        self.result = ['baz', 'foo', 'bar']

    def test_count_eq(self):
        """Will succeed"""
        self.assertCountEqual(self.result, self.expected)

    def test_list_eq(self):
        """Will fail"""
        self.assertListEqual(self.result, self.expected)

if __name__ == "__main__":
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

附注:请确保您要比较的列表中的元素是可排序的.

  • 谢谢.原来的名字是如此清晰,我见过那种方法,但是假设它检查了计数. (4认同)
  • 谢谢。但*彻头彻尾的*误导,我会称之为! (3认同)

def*_*fuz 49

稍快版本的实现(如果你知道大多数情侣列表将有不同的长度):

def checkEqual(L1, L2):
    return len(L1) == len(L2) and sorted(L1) == sorted(L2)
Run Code Online (Sandbox Code Playgroud)

比较:

>>> timeit(lambda: sorting([1,2,3], [3,2,1]))
2.42745304107666
>>> timeit(lambda: lensorting([1,2,3], [3,2,1]))
2.5644469261169434 # speed down not much (for large lists the difference tends to 0)

>>> timeit(lambda: sorting([1,2,3], [3,2,1,0]))
2.4570400714874268
>>> timeit(lambda: lensorting([1,2,3], [3,2,1,0]))
0.9596951007843018 # speed up
Run Code Online (Sandbox Code Playgroud)

  • @ inspectorG4dget:`len()`具有O(1)复杂度(常数时间).没有通过来获得价值. (16认同)
  • 您的加速来自(1)无分支(有效),(2)排序前的“len”检查。`len` 检查的时间复杂度为 O(n),并且仅在返回 `False` 的情况下有帮助。否则,通过添加两个线性通道(“L1”和“L2”各一个)会损害实际的运行时间(而不是复杂性)。因此,虽然运行时复杂度仍然是 O(nlogn)(来自排序),但 O(n) 会影响该函数“返回”所需的秒数 (2认同)
  • 如果您的列表包含像`dict`这样的无法排序的类型,则这不起作用. (2认同)

Cor*_*ein 27

特定

l1 = [a,b]
l2 = [b,a]
Run Code Online (Sandbox Code Playgroud)

在Python > = 3.0

assertCountEqual(l1, l2) # True
Run Code Online (Sandbox Code Playgroud)

在Python > = 2.7中,上面的函数被命名为:

assertItemsEqual(l1, l2) # True
Run Code Online (Sandbox Code Playgroud)

在Python <2.7

import unittest2
assertItemsEqual(l1, l2) # True
Run Code Online (Sandbox Code Playgroud)

  • **如果列表中只有唯一值** 使用 set(l1)&amp; set(2) 将它们转换为 set 并使用 assertSetEqual(l1, l2) 进行断言也有帮助。 (2认同)

ins*_*get 19

将列表转换为集合将告诉您它们包含相同的元素.但是这种方法无法确认它们包含相同数量的所有元素.例如,在这种情况下,您的方法将失败:

L1 = [1,2,2,3]
L2 = [1,2,3,3]
Run Code Online (Sandbox Code Playgroud)

您可能最好对两个列表进行排序并进行比较:

def checkEqual(L1, L2):
    if sorted(L1) == sorted(L2):
        print "the two lists are the same"
        return True
    else:
        print "the two lists are not the same"
        return False
Run Code Online (Sandbox Code Playgroud)

请注意,这不会改变两个列表的结构/内容.相反,排序会创建两个新列表

  • 在我的商店,我们使用'assertElementsEqual',对我们有意义. (3认同)