问:
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
我们需要判断a和b是相等的,因为他们有同样的元素,尽管他们的顺序不同。
但是实际情况是,list会按照顺序比对内部元素,该如何解决?
答:
O(n)复杂度: 如果内部的对象是可hash的,那么Collections下的Counter方法是最好的。
from collections import Counter
def compare(s, t):
return Counter(s) == Counter(t)
O(nlogn)复杂度:如果对象可以排序,那么sorted()方法是次优的。
def compare(s, t):
return sorted(s) == sorted(t)
O(n*n)复杂度:如果对象既不可以hash又无法排序,我们可以使用以下方法:
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
如何判断内部对象是可hash的?
在Python中,可以通过检查对象是否实现了 __hash__
方法来判断其是否可hash。一般来说,只有不可变的对象(如整数、浮点数、字符串和元组)是可hash的,而可变的对象(如列表和字典)通常不可hash。你可以使用 hash()
函数和 try-except
结构来测试一个对象是否可hash,或者使用 collections.abc.Hashable
来检查对象是否实现了 __hash__
方法。
方法 1:使用 hash()
函数
通过尝试调用 hash()
函数,可以判断对象是否可hash。如果对象不可hash,将会引发 TypeError
异常。
def is_hashable(obj):
try:
hash(obj)
return True
except TypeError:
return False
方法 2:使用 collections.abc.Hashable
Python的 collections.abc
模块提供了 Hashable
抽象基类,可以通过 isinstance()
函数来判断对象是否实现了 __hash__
方法。
from collections.abc import Hashable
def is_hashable(obj):
return isinstance(obj, Hashable)
示例
from collections.abc import Hashable
def is_hashable(obj):
return isinstance(obj, Hashable)
print(is_hashable(42)) # True,整数是可hash的
print(is_hashable([1, 2, 3])) # False,列表不可hash
print(is_hashable((1, 2, 3))) # True,元组是可hash的
print(is_hashable({1, 2, 3})) # False,集合不可hash
这两种方法都可以准确判断对象是否可hash,使用 Hashable
可能会更直观一些。
在Python中,可以通过以下方法来判断一个对象是否可排序:
-
尝试使用排序操作:通过使用
sorted()
或<
运算符来测试对象是否支持排序。如果对象不可排序,会引发TypeError
异常。 -
检查是否实现了
__lt__
方法:在Python中,排序依赖于对象实现比较运算符<
(即__lt__
方法)。如果对象实现了__lt__
方法,通常可以被排序。
方法 1:尝试排序
可以尝试使用 sorted()
函数对包含该对象的列表进行排序,如果对象不可排序,则会引发 TypeError
。
def is_sortable(obj):
try:
sorted([obj, obj])
return True
except TypeError:
return False
def is_sortable(obj):
try:
sorted([obj, obj])
return True
except TypeError:
return False
print(is_sortable(42)) # True,整数可以排序
print(is_sortable("hello")) # True,字符串可以排序
print(is_sortable([1, 2, 3])) # False,列表本身不可排序
print(is_sortable((1, 2, 3))) # False,元组本身不可排序
print(is_sortable({"a": 1})) # False,字典不可排序
方法 2:检查 __lt__
方法
通过 hasattr()
检查对象是否具有 __lt__
方法(即小于比较运算符),以此判断对象是否支持排序。
def is_sortable(obj):
return hasattr(obj, "__lt__")
def is_sortable(obj):
return hasattr(obj, "__lt__")
print(is_sortable(42)) # True,整数可以排序
print(is_sortable("hello")) # True,字符串可以排序
print(is_sortable([1, 2, 3])) # False,列表本身不可排序
print(is_sortable((1, 2, 3))) # False,元组本身不可排序
print(is_sortable({"a": 1})) # False,字典不可排序
注意,方法1更稳妥,因为即使对象有 __lt__
方法,具体实现可能仍然会导致排序异常。因此,尝试排序操作可以提供更准确的判断。