在python中如何有效的比较两个无序的列表是否包含完全同样的元素(不是set)?

问:

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__ 方法,具体实现可能仍然会导致排序异常。因此,尝试排序操作可以提供更准确的判断。

猜你喜欢

转载自blog.csdn.net/qq_73454087/article/details/143491672