检查两个无序列表是否相等

时间:2012-03-08 18:49:43

标签: python list comparison

我正在寻找一种简单(快速)的方法来确定两个无序列表是否包含相同的元素:

例如:

['one', 'two', 'three'] == ['one', 'two', 'three'] :  true
['one', 'two', 'three'] == ['one', 'three', 'two'] :  true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] :  false
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] :  false
['one', 'two', 'three'] == ['one', 'two', 'four'] :  false
['one', 'two', 'three'] == ['one'] :  false

我希望不使用地图就可以做到这一点。

8 个答案:

答案 0 :(得分:373)

Python有一个内置的数据类型,用于无序的(可散列)事物集合,称为set。如果将两个列表都转换为集合,则比较将是无序的。

set(x) == set(y)

Documentation on set


编辑:@mdwhatcott指出您要检查重复项。 set忽略这些,因此您需要一个类似的数据结构,以跟踪每个列表中的项目数。这称为multiset;标准库中的最佳近似值是collections.Counter

>>> import collections
>>> compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
>>> 
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3,3], [1,2,2,3])
False
>>> 

答案 1 :(得分:63)

如果元素总是按照您的示例进行排序,那么内置.sort()timsort)应该很快:

>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False

如果您不想进行排序,可以使用sorted()

在实践中,它可能总是比collections.Counter()快(尽管渐渐O(n)时间比O(n*log(n)) .sort()更好。测量它;如果重要的话。

答案 2 :(得分:17)

sorted(x) == sorted(y)

从此处复制:Check if two unordered lists are equal

我认为这是这个问题的最佳答案,因为

  1. 比使用this answer
  2. 中指出的计数器更好
  3. x.sort()对x进行排序,这是副作用。 sorted(x)返回一个新列表。

答案 3 :(得分:14)

您希望查看它们是否包含相同的元素,但不关心顺序。

您可以使用一套:

>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True

但是set对象本身只包含每个唯一值的一个实例,并且不会保留顺序。

>>> set(['one', 'one', 'one']) == set(['one'])
True

因此,如果跟踪重复项/长度很重要,您可能还需要检查长度:

def are_eq(a, b):
    return set(a) == set(b) and len(a) == len(b)

答案 4 :(得分:4)

如果您不想使用集合库,您可以始终执行以下操作: 鉴于ab是您的列表,以下内容返回匹配元素的数量(它考虑订单)。

sum([1 for i,j in zip(a,b) if i==j])

因此,

len(a)==len(b) and len(a)==sum([1 for i,j in zip(a,b) if i==j])
如果两个列表相同,则

将为True,包含相同的元素并且顺序相同。否则False

因此,您可以像上面的第一个响应一样定义比较函数,但没有集合库。

compare = lambda a,b: len(a)==len(b) and len(a)==sum([1 for i,j in zip(a,b) if i==j])

>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3], [1,2,4])
False

答案 5 :(得分:3)

上述问题的一个答案是: -

让两个列表为list1和list2, 并且你的要求是确保两个列表是否具有相同的元素,然后按照我的说法,以下将是最好的方法: -

if ((len(list1) == len(list2)) and
   (all(i in list2 for i in list1))):
    print 'True'
else:
    print 'False'

上面的代码将根据您的需要工作,即list1的所有元素是否在list2中,反之亦然。

但是如果你只想检查list1中是否存在list1的所有元素,那么你只需要使用下面的代码: -

if all(i in list2 for i in list1):
    print 'True'
else:
    print 'False'

不同之处在于,如果list2包含一些额外元素以及list1的所有元素,则后者将打印True。简单来说,它将确保list1的所有元素都应该出现在list2中,而不管list2是否有一些额外的元素。

答案 6 :(得分:3)

假设您已经知道列表具有相同的大小,当且仅当两个向量完全相同(包括顺序)时,以下将保证为真

functools.reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, listA, ListB), True)

示例:

>>> from functools import reduce
>>> def compvecs(a,b):
...     return reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, a, b), True)
... 
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compvecs(a=[1,2,3,4], b=[1,2,3,4])
True
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compare_vectors(a=[1,2,3,4], b=[1,2,2,4])
False
>>> 

答案 7 :(得分:2)

获取列表的字符串表示并比较它们怎么样?

>>> l1 = ['one', 'two', 'three']
>>> l2 = ['one', 'two', 'three']
>>> l3 = ['one', 'three', 'two']
>>> print str(l1) == str(l2)
True
>>> print str(l1) == str(l3)
False