检查两个无序列表是不是相等[重复]

Posted

技术标签:

【中文标题】检查两个无序列表是不是相等[重复]【英文标题】:Check if two unordered lists are equal [duplicate]检查两个无序列表是否相等[重复] 【发布时间】:2012-03-26 06:11:29 【问题描述】:

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

例如:

['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

我希望在不使用地图的情况下做到这一点。

【问题讨论】:

(在 o(n) 空间中执行此操作而不修改输入看起来是一个挑战。)将 ['one', 'one', 'two'] == ['one', 'two', 'two'] 添加到示例中。 【参考方案1】:

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
>>> 

【讨论】:

注意:因为使用 set() 删除重复项,所以对于提供的第三个示例,此解决方案返回 True 而不是 False。 如果您不关心重复,这是最好的答案。如果您想检查它们是否具有 相同 元素,Suhail 的回答 ***.com/a/19244156/403423 是最好的。 如果您因为有两个看起来相同但评估结果不相等(就像我所做的那样)而来到这里,请检查这些对象的 __hash__ 函数以验证相等的对象是否具有相等的哈希值.我的没有。【参考方案2】:

如果元素总是几乎按照您的示例排序,那么内置 .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() 更好)。测量它;如果它很重要。

【讨论】:

sorted(a) == sorted(b) 是我认为这里最干净的方法。我认为这个答案应该是公认的。 我不认为这个答案是正确的,因为在列表上调用sort() 可能会改变其项目的顺序,如果我们对两个列表进行比较并且之后它们变得不同,这是不可接受的。 @Reorx:为什么投反对票?您是否阅读过:“如果您不想就地排序,可以使用 sorted()。” 在答案中? @JFSebastian 很抱歉忽略了这些话,但我认为一个好的答案应该是明确的,直接告诉读者什么是解决问题的最佳方法,而不仅仅是提供一个有争议的方法和一个可有可无的解释在它下面。如果您可以增强您的答案并清楚地说明使用.sort()sorted() 的区别,我将撤回反对票。谢谢你:) @Reorx:如果可以的话,最好的方法是就地排序:它可以避免创建不必要的副本。它并不总是可取的,因此提到了sorted()。如果你不知道它的作用;点击链接。【参考方案3】:
sorted(x) == sorted(y)

从这里复制:Check if two unordered lists are equal

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

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

【讨论】:

@TedKleinBergman 他们提供了归属,他们没有复制另一个答案,他们将有用的(+19)评论转换为答案。这很有价值。 这是真正的答案 - 它可以处理 UNHASHABLE 列表元素。 set() 有时不是答案(大小、重复...)。 嗯,仍然 - 值得一读 Raymond 的回答:***.com/a/7829388/1338797 - 有些东西,比如dicts,是不可排序的......【参考方案4】:

你想看看它们是否包含相同的元素,但不关心顺序。

你可以使用一个集合:

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

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

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

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

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

【讨论】:

+1 好点,我没注意到!另一方面,仅仅检查长度是不够的(否则[1,1,2]==[1,2,2])——你必须计算所有对象。 如果您想检查 相同 元素(包括重复项),这些解决方案(即使是最后一个)都不起作用 are_eq([1,2,2],[1,1,2]) == True投反对票 are_eq([1,2,2],[1,1,2]) == True投反对票【参考方案5】:

如果您不想使用集合库,您可以随时执行以下操作: 鉴于 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])

如果两个列表相同、包含相同元素且顺序相同,则为TrueFalse 否则。

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

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

【讨论】:

【参考方案6】:

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

让这两个列表分别是list1和list2, 并且您的要求是确保两个列表是否具有相同的元素,那么根据我的说法,以下将是最好的方法:-

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

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

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

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

不同的是,如果 list2 包含一些额外的元素以及 list1 的所有元素,则后者将打印 True。简单来说,就是保证list1的所有元素都应该出现在list2中,不管list2有没有多余的元素。

【讨论】:

def same(list1, list2): return ((len(list1) == len(list2)) and (all(i in list2 for i in list1))); same((1,1,2), (1,2,2))【参考方案7】:

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

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
>>> 

【讨论】:

【参考方案8】:

如何获取列表的字符串表示并比较它们?

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

【讨论】:

这是两个无序列表。

以上是关于检查两个无序列表是不是相等[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个循环中比较两个列表的值是不是相等?

根据值列表检查变量是不是相等

将列表拆分为 2 个相等和的列表

如何在javascript中检查两个数字是不是相等[重复]

HTML / CSS:导航元素中的无序列表略微向右偏移[重复]

Java ArrayList - 我如何判断两个列表是不是相等,顺序无关紧要?