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

Pau*_*aul 234 python comparison list

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

例如:

['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
Run Code Online (Sandbox Code Playgroud)

我希望不使用地图就能做到这一点.

Kat*_*iel 405

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

set(x) == set(y)
Run Code Online (Sandbox Code Playgroud)

关于的文件 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
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 注意:因为使用set()删除重复项,所以对于提供的第三个示例,此解决方案将返回True而不是False. (79认同)
  • 如果您最终因为有两个看起来相同但评估结果不相等(如我所做的)而来到这里,请检查这些对象的“__hash__”函数以验证相等的对象是否具有相等的哈希值。我的没有。 (4认同)
  • 如果你不关心重复,这是最好的答案.如果你想检查他们是否有*相同的*元素,Suhail的答案http://stackoverflow.com/a/19244156/403423是最好的. (2认同)
  • 这不是正确的答案,不应被接受。排序(x)==排序(y)应该是正确的答案。 (2认同)

jfs*_*jfs 68

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

>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False
Run Code Online (Sandbox Code Playgroud)

如果你不想在现场排序,你可以使用sorted().

在实践中它可能永远是那么快collections.Counter()(尽管渐进O(n)时间是更好,然后O(n*log(n))进行.sort()).测量它; 如果重要的话.

  • `排序(a)==排序(b)`是我认为这里最干净的方法.我认为这个答案应该是被接受的答案. (19认同)
  • @Reorx:为什么选择downvote?你读过:*"如果你不想在里面排序你可以使用sorted()."*在答案中? (3认同)
  • @Reorx:如果可以的话,最好的方法就是排序:避免创建不必要的副本.因此并不总是需要`sorted()`.如果你不知道它做了什么; 单击链接. (3认同)
  • 我不认为这个答案是正确的,因为调用`排序()`上的列表中可以改变它的项目的顺序,这是不能接受的,如果我们做的两个列表进行比较,他们就成为不同的算账. (2认同)
  • @JFSebastian 很抱歉忽略了这些词,但我认为一个好的答案应该是明确的,并直接告诉读者解决问题的最佳方法是什么,而不仅仅是提供一种有争议的方法,并在其下提供可有可无的解释。如果您可以增强您的答案并清楚地说明使用 `.sort()` 和 `sorted()` 的区别,我将撤回反对票。谢谢 :) (2认同)

小智 19

sorted(x) == sorted(y)
Run Code Online (Sandbox Code Playgroud)

从这里复制:检查两个无序列表是否相等

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

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


小智 16

您想要查看它们是否包含相同的元素,但不关心顺序.

你可以使用一套:

>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True
Run Code Online (Sandbox Code Playgroud)

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

>>> set(['one', 'one', 'one']) == set(['one'])
True
Run Code Online (Sandbox Code Playgroud)

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

def are_eq(a, b):
    return set(a) == set(b) and len(a) == len(b)
Run Code Online (Sandbox Code Playgroud)

  • +1好点,我没注意到!另一方面,仅检查长度是不够的(否则`[1,1,2] == [1,2,2]`) - 你必须计算所有对象. (10认同)
  • downvote为`are_eq([1,2,2],[1,1,2])== True` (3认同)
  • downvote为`are_eq([1,2,2],[1,1,2])== True` (3认同)

小智 6

假设您已经知道列表大小相等,当且仅当两个向量完全相同(包括顺序)时,以下内容将保证 True

functools.reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, listA, ListB), True)
Run Code Online (Sandbox Code Playgroud)

例子:

>>> 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
>>> 
Run Code Online (Sandbox Code Playgroud)