【问题标题】:How to properly use recursion in this (simple) python procedure?如何在这个(简单)python 过程中正确使用递归?
【发布时间】:2012-04-20 08:24:13
【问题描述】:

各位,我写了一个函数来测试两个输入(a和b)是否具有相同的数据结构,这样:

print same_structure([1, 0, 1], [a, b, c])
#>>> True
#print same_structure([1, [0], 1], [2, 5, 3])
>>> False
#print same_structure([1, [2, [3, [4, 5]]]], ['a', ['b', ['c', ['d', 'e']]]])
>>> True  
#print same_structure([1, [2, [3, [4, 5]]]], ['a', ['b', ['c', ['de']]]])
>>> False

这个函数(在我的实现中)使用递归。我是递归的初学者,我仍然难以递归思考。另外,为了避免欺骗答案,我想使用我自己的(凌乱的)代码,并通过它学习正确使用递归调用(使用此代码行:'same_structure return (a [i], b [e])' )。有人可以展示如何在下面的代码中正确使用递归吗? 提前感谢您的帮助!!!

def is_list(p):
return isinstance(p, list)

def same_structure(a,b):
    if not is_list(a) and not is_list(b):
        print '#1'
        return True
    else:
        if is_list(a) and is_list(b):
            print '#2'
            if len(a) != len(b):
                print '#3'
                return False
            if len(a) == len(b):
                print '#4'
                for e in range(len(a)):
                    print 'e = ', e, 'a[e]= ', a[e], 'b[e]=', b[e]
                    return same_structure(a[e], b[e])           
        else:
            return False

【问题讨论】:

    标签: python data-structures recursion


    【解决方案1】:

    以下作品:

    def same_structure(a, b):
        if isinstance(a, list) and isinstance(b, list) and len(a) == len(b):
            return all(same_structure(A, B) for A, B in zip(a, b))
        return (not isinstance(a, list) and not isinstance(b, list))
    

    在编写递归函数时,您首先需要提出基本情况,即只返回一个值而不是调用任何递归。这里的基本情况是以下条件之一:

    • a 是一个列表,b 不是,反之亦然:return False
    • ab 都是列表,但它们的长度不同:return False
    • ab 都不是列表:返回 True

    如果ab 都是列表并且它们具有相同的长度,我们现在需要递归地检查这些列表的每个元素。 zip(a, b) 提供了一种方便的方法来迭代每个列表中的元素,如果same_structure() 的结果对于任何两个子元素都是 False,我们希望整个函数返回 False。这就是使用all() 的原因,如果您不熟悉all(),它等效于(但更有效)以下循环:

    match = True
    for A, B in zip(a, b):
        if not same_structure(A, B):
            match = False
            break
    return match
    

    以下是您如何在不进行太多更改的情况下重写您的函数,逻辑实际上与我的解决方案非常相似,但就在 print '#4' 下方,您过早地从该循环返回:

    def same_structure(a,b):
        if not is_list(a) and not is_list(b):
            print '#1'
            return True
        else:
            if is_list(a) and is_list(b):
                print '#2'
                if len(a) != len(b):
                    print '#3'
                    return False
                if len(a) == len(b):
                    print '#4'
                    for e in range(len(a)):
                        print 'e = ', e, 'a[e]= ', a[e], 'b[e]=', b[e]
                        if not same_structure(a[e], b[e]):
                            return False
                    return True        
            else:
                return False
    

    【讨论】:

    • 嗨,@F.J!你的代码比我的要好得多(谢谢!)。但我不认为在这个硬件中使用 zip() 或 all()。另外,为了避免欺骗答案,我想拿我自己的(凌乱的)代码并通过它,学习如何使用递归调用(修复此代码行'same_structure return(a [i],b [e])' )。
    • @Pythonista'sApprentice 我大约 10 分钟前进行了编辑,其中包含您的函数的编辑版本,它应该可以工作,同时仍然遵循这些要求。
    【解决方案2】:

    你只是在做第一次递归调用,因为你马上就回来了。

    如果我明白你想要做什么,你需要用子元素调用same_structure,并检查它的返回值(不是立即返回)。如果任何一个调用的结果为假,则返回假,否则,返回真。

    【讨论】:

      【解决方案3】:

      试试这个解决方案,它适用于您的所有示例,它以递归、函数式编程风格编写,但不使用zipall 等。在每个步骤中只使用切片来减小列表的大小:

      def same_structure(a, b):
          if a == [] or b == []:
              return a == b
          elif is_list(a[0]) != is_list(b[0]):
              return False
          elif not is_list(a[0]):
              return same_structure(a[1:], b[1:])
          else:
              return same_structure(a[0], b[0]) and same_structure(a[1:], b[1:])
      

      【讨论】:

        猜你喜欢
        • 2022-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-05
        • 1970-01-01
        • 2012-07-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多