a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
考虑到a和b具有完全相同的元素,只是顺序不同,因此应被视为相等。
问题在于,我的实际列表将由对象(即我的类实例)而不是整数组成。
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
考虑到a和b具有完全相同的元素,只是顺序不同,因此应被视为相等。
问题在于,我的实际列表将由对象(即我的类实例)而不是整数组成。
O(n):如果你的对象是可哈希的,则最好使用Counter()方法:
def compare(s, t):
return Counter(s) == Counter(t)
O(n log n): 如果你的对象是可排序的,那么sorted()方法是次优解:
def compare(s, t):
return sorted(s) == sorted(t)
O(n * n): 如果对象既不可哈希,也不可排序,则可以使用相等性:
def compare(s, t):
t = list(t) # make a mutable copy
try:
for elem in s:
t.remove(elem)
except ValueError:
return False
return not t
Counter
方法的时间复杂度是O(n)
,但是对于在计数器字典中插入键/值呢?嗯,我想这会使它变成O(n + log(n))
。 - Jean-François FabreO(n + log(n))
”可以简化为“O(n)
”,因为n
是更高的复杂度级别。” - StriplingWarrior您可以对两者进行排序:
sorted(a) == sorted(b)
使用 计数排序 也能更有效率(但需要对象可哈希)。
>>> from collections import Counter
>>> a = [1, 2, 3, 1, 2, 3]
>>> b = [3, 2, 1, 3, 2, 1]
>>> print (Counter(a) == Counter(b))
True
__hash__
方法即可,但对于集合类可能是不可能的。 - Jochen Ritzelsorted([0, 1j])
。 - John La RooyCounter()
,它的时间复杂度为 O(n)。
如果你知道这些项目始终是可排序的,你可以使用 sorted()
,它的时间复杂度为 O(n log n)。len(a)==len(b) and all(a.count(i)==b.count(i) for i in a)
assertCountEqual(first, second, msg=None)
测试序列first是否包含与second相同的元素,无论其顺序如何。如果不相同,则会生成列出序列之间差异的错误消息。最好的方法是对列表进行排序并进行比较。(使用Counter
无法处理不可哈希的对象。)对于整数,这很简单:
sorted(a) == sorted(b)
对于任意对象,情况会变得有些棘手。如果你关心对象的身份,即是否在两个列表中都有相同的对象,那么可以使用id()
函数作为排序键。
sorted(a, key=id) == sorted(b, key==id)
key=
参数,因为您可以将任何对象与任何对象进行比较。排序是任意的但稳定的,因此对于此目的它可以很好地工作;对象的顺序无关紧要,只要两个列表的排序方式相同即可。然而,在Python 3中,许多情况下禁止比较不同类型的对象 - 例如,您不能将字符串与整数进行比较 - 因此,如果您将具有各种类型的对象,则最好明确使用对象的ID。repr()
排序。当然,这可能会浪费大量额外的时间和内存来构建repr()
字符串等。sorted(a, key=repr) == sorted(b, key==repr)
__lt__()
方法,让对象知道如何与其他对象进行比较。然后你就可以直接排序了,不用再关心key=
参数。当然,您也可以定义__hash__()
并使用Counter
更快地完成操作。如果要在测试环境中执行比较,请使用assertCountEqual(a, b)
(py>=3.2
)和assertItemsEqual(a, b)
(2.7<=py<3.2
)。
也适用于不可哈希对象的序列。
len(a) == len(b)
而不是 MagicCounter(a) == MagicCounter(b)
,其中 MagicCounter
是一个可以处理不可哈希对象的 Counter
... - Tomasz Gandor如果列表中包含不可哈希的项目(例如对象列表),您可能可以使用Counter类和id()函数,例如:
from collections import Counter
...
if Counter(map(id,a)) == Counter(map(id,b)):
print("Lists a and b contain the same objects")
设a、b为列表
def ass_equal(a,b):
try:
map(lambda x: a.pop(a.index(x)), b) # try to remove all the elements of b from a, on fail, throw exception
if len(a) == 0: # if a is empty, means that b has removed them all
return True
except:
return False # b failed to remove some items from a
不需要使它们可哈希或排序。
a
支持pop
(可变)和index
(序列)。Raymond的假设两者都不支持,而gnibbler的则仅假设为序列。 - agfif ((len(a) == len(b)) and
(all(i in a for i in b))):
print 'True'
else:
print 'False'
a
和b
中的所有元素都相同,无论它们是否按相同顺序排列。from collections import defaultdict
def _list_eq(a: list, b: list) -> bool:
if len(a) != len(b):
return False
b_set = set(b)
a_map = defaultdict(lambda: 0)
b_map = defaultdict(lambda: 0)
for item1, item2 in zip(a, b):
if item1 not in b_set:
return False
a_map[item1] += 1
b_map[item2] += 1
return a_map == b_map
如果数据高度无序,排序可能会非常慢(当项目具有某些排序程度时,timsort是额外好的)。同时对两个列表进行排序也需要完全迭代。
与其改变列表,不如分配一个集合并进行左-右成员检查,一路上保持每个项目存在的数量计数:
False
。a
中遇到任何不在列表b
中的项目,则可以返回False
a_map
和b_map
的值,以找出它们是否匹配。这使您能够在迭代两个列表之前在许多情况下进行短路。
_list_eq([0, 0, 1] [0, 1, 1])
- greybeard
len()
。 - greybeard