Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何深入比较Python中的嵌套类型_Python - Fatal编程技术网

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

如何深入比较Python中的嵌套类型,python,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 是否有一

在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

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

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

要扩展我的评论,可以递归创建我称之为“类型映射”的内容:

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

如果您需要处理列表以外的事情,您可以简单地将
isinstance
检查扩展到
(列表,元组)
,但您可能会很快遇到类似
str
(递归迭代字符串是一个问题,因为单个字符或空字符串本身就是一个iterable,因此您的程序会爆炸)和
dict
(排序问题,比较键和/或值,…).

您是否也关心相同的大小?还是只是确保无论其中有多少个,它们都必须在结构中具有相同的类型?因为有一个通用的方法意味着这是一个定义明确的问题,但不是。列表的长度是否与其“类型”相关?如何处理非同质容器类型?我们只讨论一个嵌套级别吗?您可以递归创建两个结构,只包含每个位置的对象类型,然后直接比较它们-
[str,str]!=[int,int]
,例如。您是否可以假设结构包含同构类型,或者您最终会看到例如
deepcompare(['a',1],'b',2])
(结果应该是什么)?@tzaman的观点很好,请看editI将在此处使用
any
。它会在破坏您的条件时立即短路。此外,这只处理单个级别如果您创建一组所有类型,并且只检查该集的长度是否为1?
types={type(x),则
getDeepTypes(items)
将更有效对于项中的x}
如果len(types)==1返回types.pop()
.Nice!虽然这要更一般一些,但是
类型映射中的第一行是否应该检查
列表\u或\u obj
是否可iterable,而不是它是否是列表?@spiffman这是一个要求?可iterable的问题是,例如字符串和字典是可iterable的,但您可能想要处理这些不同的问题不一定,我只是想知道这是否会提供一个更通用的解决方案,但你是对的,字符串大小写在这里特别有问题。@JornSharpe这是一个解决方法,可以清除。你也可以使用
collections.Iterable
进行类型检查,以使它更全面。@Kasramvd请阅读,我指出了为什么简单地检查iterables并不是一个灵丹妙药
def deepcompare(a, b):
    return typemap(a) == typemap(b)