如何比较嵌套结构?

时间:2019-07-19 14:25:17

标签: python-3.x algorithm

我想比较两个嵌套结构,例如比较[[[1],[2],[3]],[2],3][1,'a',[[[1]],['abc','d']]]。怎么办?

3 个答案:

答案 0 :(得分:3)

从您的评论看来,列表中元素的类型和数量似乎都不重要,而列表本身的“嵌套结构”似乎都不重要。因此,您可以从列表中递归地删除不是另一个嵌套列表的所有内容,然后比较剩下的内容。

def purge(lst): 
    return [purge(x) for x in lst if isinstance(x, list)] 

a = [[[1],[2],[3]],[2],3]                                               
b = [1,'a',[[[1]],['abc','d']]]                                         
purge(a)                                                                
# [[[], [], []], []]
purge(b)                                                                
# [[[[]], []]]
purge(a) == purge(b)                                                    
# False

随意将其扩展到其他结构,例如dictset

如果类型确实很重要,但不重要,则可以使用此变体,它将保留每个列表项的type,但折叠相同的连续条目(请注意,它也折叠[7],[8],[9][int](第一个版本除外):

import itertools

def purge2(lst):
    tmp = [purge2(x) if isinstance(x, list) else type(x).__name__ for x in lst]
    return [k for k, g in itertools.groupby(tmp)]

c = [[[1,2,3],["a","b"],4,[5,6]],[7],[8],[9]]
purge2(c)
# [[['int'], ['str'], 'int', ['int']], ['int']]

请注意,这种方式不能直接比较“已清除”列表,至少如果空列表应与具有任何内容的列表匹配,则至少不能如此。为此,您将需要另一种递归比较方法。


相反,您还可以定义一个保留除列表结构以外的函数,也许您也可以将其用于其他比较...

def leafs(lst): 
    return [x for y in lst 
              for x in (leafs(y) if isinstance(y, list) else [y])] 

leafs(a)                                                               
# [1, 2, 3, 2, 3]
leafs(b)                                                               
# [1, 'a', 1, 'abc', 'd']

答案 1 :(得分:0)

以下功能通过比较列表的大小来达到您想要的结果:

def compare_struc(arr1, arr2):
    len1 = len(arr1)
    len2 = len(arr2)

    if len1 == len2:
        return True
    else:
        return False

def main():
    testlist1 =  [[1],[2],[3]]
    testlist2 = [[],[],[]]

    answer = compare_struc(testlist1, testlist2)

    print("The answer was: ", answer)

main()
  

输出:

     

答案是:正确

答案 2 :(得分:0)

从这个问题尚不清楚,确定两个结构是否等效的标准是什么? tobias_k's answer是一个合理的猜测,这是另一个。我认为,如果项目不是列表,或者它是列表但不包含更多列表,则它是“叶”。有了这个,我们可以拥有这个:

def is_leaf(s):
    return not (isinstance(s, list) and any(isinstance(i, list) for i in s))

def have_similar_structure(s1, s2):
    if is_leaf(s1):
        return is_leaf(s2)
    elif is_leaf(s2):
        return False
    # Both are non-leaf
    if len(s1) != len(s2):
        return False
    return all(have_similar_structure(i1, i2) for i1, i2 in zip(s1, s2))

print(have_similar_structure([[[1], [2], [3]], [2], 3], [[[], [], []], [], None]))
# True
print(have_similar_structure([[]], [1, 2, [3]]))
# False
print(have_similar_structure([[]], [1]))
# False