我正在寻找一种简单(快速)的方法来确定两个无序列表是否包含相同的元素:
例如:
['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
我希望不使用地图就可以做到这一点。
答案 0 :(得分:373)
Python有一个内置的数据类型,用于无序的(可散列)事物集合,称为set
。如果将两个列表都转换为集合,则比较将是无序的。
set(x) == set(y)
编辑:@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
我认为这是这个问题的最佳答案,因为
答案 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)
如果您不想使用集合库,您可以始终执行以下操作:
鉴于a
和b
是您的列表,以下内容返回匹配元素的数量(它考虑订单)。
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