如何重写此递归函数以生成具有 yield 的生成器?

问题描述

我很难理解如何在递归函数中使用 yield。是否有可能,或者我是否必须重写函数以进行迭代才能使用 yield

def extract_pairs(li,return_list):
    if len(li) == 2 and type(li[0]) != list:
        return_list.append(li)
        return

    for item in li:
        extract_pairs(item,return_list)

ret = []
extract_pairs([1,1],ret)
print(ret) #[[1,1]]

ret = []
extract_pairs([[1,[2,2]],ret)
print(ret) # [[1,2]]

ret = []
extract_pairs([[[1,1]],2],[]],2]]

解决方法

我不确定您为什么要将生成器累积到参考中。无论如何,我提供了三种解决方案:迭代、递归和使用引用的递归。

def is_pair(li):
    return len(li) == 2 and type(li[0]) != list

# Pretty much what you did,except we don't use a ref
def extract_pairs(li):
    for item in li:
        if is_pair(item):
            yield item

# If the list is empty,then terminate the generator
# otherwise yield if the head of the list is a pair
# then,recurse on the tail of the list
def extract_pairs_rec(li):
    if li == []:
        return
    elif is_pair(li[0]):
        yield li[0]
    
    yield from extract_pairs_rec(li[1:])

# This is pretty much what we did above,# except that we append to the reference instead of `yield`ing
def extract_pairs_rec_by_ref(li,ref):
    if li == []:
        return
    elif is_pair(li[0]):
        ref.append(li[0])

    yield from extract_pairs_rec_by_ref(li[1:],ref)
print(list(extract_pairs([[1,1],[],[2,2],[]])))

ref = []
list(extract_pairs_rec_by_ref([[1,[]],ref))
print(ref)

print(list(extract_pairs_rec([[1,[]])))

# All of them is then equal to
# [[1,2]]