如何深入比较Python中的嵌套类型

时间:2016-03-16 17:12:22

标签: python

在python中,很容易测试两个变量是否具有相同的顶级类型:

In [1]: s1 = 'bob'
In [2]: s2 = 'tom'
In [3]: type(s1) == type(s2)
Out[3]: True

但是在嵌套类型的情况下,它并不容易:

In [4]: strlist = ['bob', 'tom']
In [5]: intlist = [5, 6, 7]
In [6]: type(strlist) == type(intlist)
Out[6]: True

是否有一般方式来“深入”比较两个变量:

deepcompare(['a', 'b'], [1, 2]) == False
deepcompare([42, 43], [1, 2]) == True

编辑:

为了更详细地定义问题,假设这包括列表长度和异构列表类型:

deepcompare([1, 2, 3], [1, 2]) == False
deepcompare([1, 3], [2, 'b']) == False
deepcompare([1, 'a'], [2, 'b']) == True

2 个答案:

答案 0 :(得分:2)

要扩展我的评论,您可以递归创建我称为“type map”的内容:

def typemap(lst_or_obj):
    if not isinstance(lst_or_obj, list):
        return type(lst_or_obj)
    return [typemap(obj) for obj in lst_or_obj]

然后使用它来获取你的结构中的类型:

a = [1, 2, ['three', 4]]
b = [5, 6, ['seven', 8]]
c = [9, 10, [11, 'twelve']]

ta = typemap(a)
tb = typemap(b)
tc = typemap(c)

print(ta)
print(tb)
print(tc)

print(ta == tb)
print(ta == tc)

输出:

[<class 'int'>, <class 'int'>, [<class 'str'>, <class 'int'>]]
[<class 'int'>, <class 'int'>, [<class 'str'>, <class 'int'>]] 
[<class 'int'>, <class 'int'>, [<class 'int'>, <class 'str'>]]
True
False

然后你的功能很简单:

def deepcompare(a, b):
    return typemap(a) == typemap(b)

如果您需要处理列表以外的其他内容,您可以轻松地将isinstance检查扩展为(list, tuple),但您可以快速遇到str之类的问题(递归迭代) over strings是一个问题,因为单个字符或空字符串本身就是一个可迭代的,所以你的程序会爆炸)和dict(排序问题,比较键和/或值,......)。

答案 1 :(得分:1)

我这样做的方法是使用这个函数:

def getDeepTypes(items):
    types = [type(x) for x in items]
    return (types[0] if all(x == types[0] for x in types) else None)

这使用各种列表推导来获取列表的深层类型。如果它们不是全部相同,则返回None

>>> getDeepTypes([1, 2, 3])
int
>>> getDeepTypes(["foo", "bar"])
str
>>> print(getDeepTypes([1, "foo"]))
None

所以你可以这样做:

getDeepTypes(['a', 'b']) == getDeepTypes([1, 2]) # False
getDeepTypes([42, 43]) == getDeepTypes([1, 2]) # True