Python I';我正在编写一个函数,它将使用递归返回嵌套列表中的一组唯一元素

Python I';我正在编写一个函数,它将使用递归返回嵌套列表中的一组唯一元素,python,recursion,nested-lists,Python,Recursion,Nested Lists,这就是我现在所做的 def unique(L): ''' Returns set of unique elements in nested list L Ex. unique([ 2, 1, 4, [ 3, [3, 4], 2 ], [2, 5, 6], 4, [ 2, 1 ]]) returns: {1, 2, 3, 4, 5, 6} ''' result = set() for item in L:

这就是我现在所做的

def unique(L):
    '''
    Returns set of unique elements in nested list L
    Ex.      unique([ 2, 1, 4, [ 3, [3, 4], 2 ], [2, 5, 6], 4, [ 2, 1 ]])
    returns: {1, 2, 3, 4, 5, 6}
    '''
    
    result = set()
    for item in L:
        if isinstance(item, list):
            unique(item)
        else:
            result.add(item)
    return result
但是当我
打印(唯一([2,1,4,3,4,2],[2,5,6,4,2,1]))

结果是{1,2,4}。 我试图弄明白为什么递归没有选择嵌套列表中的5和6?
我只是想掌握递归的概念,一开始很难。提前谢谢

您没有使用
unique(item)
的结果,每个
结果都是其方法调用的本地结果。您需要当前和调用返回内容的并集

def unique(L):
    result = set()
    for item in L:
        if isinstance(item, list):
            result = result.union(unique(item)) # with method
            # result |= unique(item)            # with operator
        else:
            result.add(item)
    return result

print(unique([2, 1, 4, [3, [3, 4], 2], [2, 5, 6], 4, [2, 1]]))  # {1, 2, 3, 4, 5, 6}

您没有使用
unique(item)
的结果,每个
result
都是其方法调用的本地结果。您需要当前和调用返回内容的并集

def unique(L):
    result = set()
    for item in L:
        if isinstance(item, list):
            result = result.union(unique(item)) # with method
            # result |= unique(item)            # with operator
        else:
            result.add(item)
    return result

print(unique([2, 1, 4, [3, [3, 4], 2], [2, 5, 6], 4, [2, 1]]))  # {1, 2, 3, 4, 5, 6}

当遇到子列表时,可以递归地
set.union

def unique(L):
    result = set()
    for item in L:
        if isinstance(item, list):
            result |= unique(item) # recurse, then union with current set
        else:
            result.add(item)
    return result

>>> unique([ 2, 1, 4, [ 3, [3, 4], 2 ], [2, 5, 6], 4, [ 2, 1 ]])
{1, 2, 3, 4, 5, 6}

在当前实现中,您调用
unique(item)
,但不使用该递归调用的结果,因此返回的
结果将被丢弃,并且不会与当前项集一起累积。

当遇到子列表时,您可以递归地
set.union

def unique(L):
    result = set()
    for item in L:
        if isinstance(item, list):
            result |= unique(item) # recurse, then union with current set
        else:
            result.add(item)
    return result

>>> unique([ 2, 1, 4, [ 3, [3, 4], 2 ], [2, 5, 6], 4, [ 2, 1 ]])
{1, 2, 3, 4, 5, 6}

在当前的实现中,您调用
unique(item)
,但不使用递归调用的结果,因此返回的
结果将被丢弃,而不会与当前的项集一起累积。

您只是忘记了使用递归调用来更新
结果

...
if isinstance(item, list):
    result.update(unique(item))
...
输出:

{1, 2, 3, 4, 5, 6}

您只是忘记了使用递归调用来更新
结果

...
if isinstance(item, list):
    result.update(unique(item))
...
输出:

{1, 2, 3, 4, 5, 6}

一个相当优雅的方法是将压扁和布景制作分开

def展平(嵌套_列表):
如果isinstance(嵌套列表,列表):
对于嵌套列表中的x:
对于展平中的y(x):
产量y
其他:
产生嵌套列表
def唯一(嵌套_列表):
返回集(展平(嵌套列表))
这不是展平嵌套列表的最有效方法。如果我们有一个嵌套
n
层的
n
元素列表,则需要
O(n^2)
时间才能将其展平。为了更快的压平,我们必须更聪明

类迭代器: 定义初始化(自嵌套列表): self.stack=[iter((嵌套的_列表,)] 定义(自我): 回归自我 定义下一个(自我): 而self.stack: top\u most=自堆栈[-1] 尝试: 下一项=下一项(最上面) 如果存在(下一项,列表): self.stack.append(iter(下一项)) 其他: 返回下一个项目 除停止迭代外: self.stack.pop() 提出停止迭代 def唯一(嵌套_列表): 返回集(迭代器(嵌套的_列表))

假设参考图形成一棵树,此解决方案在总空间上是线性的。

一种相当优雅的方法是将展平与设置分离

def展平(嵌套_列表):
如果isinstance(嵌套列表,列表):
对于嵌套列表中的x:
对于展平中的y(x):
产量y
其他:
产生嵌套列表
def唯一(嵌套_列表):
返回集(展平(嵌套列表))
这不是展平嵌套列表的最有效方法。如果我们有一个嵌套
n
层的
n
元素列表,则需要
O(n^2)
时间才能将其展平。为了更快的压平,我们必须更聪明

类迭代器: 定义初始化(自嵌套列表): self.stack=[iter((嵌套的_列表,)] 定义(自我): 回归自我 定义下一个(自我): 而self.stack: top\u most=自堆栈[-1] 尝试: 下一项=下一项(最上面) 如果存在(下一项,列表): self.stack.append(iter(下一项)) 其他: 返回下一个项目 除停止迭代外: self.stack.pop() 提出停止迭代 def唯一(嵌套_列表): 返回集(迭代器(嵌套的_列表))


假设引用图形成一棵树,此解决方案在总空间量上是线性的。

有人可能会提到,主要问题是OP根本不处理递归调用的输出。@schwobasegl Good point,让我编辑一下我的答案,详细说明一下,有人可能会提到,主要的问题是OP根本不处理递归调用的输出。@schwobasegll很好,让我编辑我的答案来详细说明一下,哦,因此对于每个嵌套列表,我需要使用.union方法更新结果集?@显然,如果对新值调用
unique
,则需要在父项yes中使用该调用的结果,为什么重新绑定
result
,而不是只更新它?我明白了,所以这里有两种方法可以得到包含所有值的结果的相同结果@azrooh因此,对于每个嵌套列表,我需要使用.union方法更新结果集?@显然,如果对新值调用
unique
,则需要在父对象中使用该调用的结果,而不是仅更新它?我明白了,所以这里有两种方法可以得到包含所有值的结果的相同结果@azro@azro你怎么知道的?哈哈,是的,这是正确的,这是我写的第一个递归函数。试图理解这些原则。谢谢你们两位的意见!关于我下面的问题post@azro对不起,你为什么告诉我?你想让我编辑并解释它吗?仅仅说“他忘了”是错误的,我不在乎你怎么处理它information@azro你怎么知道的?哈哈,是的,这是正确的,这是我写的第一个递归函数。试图理解这些原则。谢谢你们两位的意见!关于问题