【问题标题】:Python recursion with a nested list带有嵌套列表的 Python 递归
【发布时间】:2021-01-12 21:30:09
【问题描述】:

我正在尝试创建一个递归函数,该函数通过单个字符串遍历任何级别的嵌套列表,无论给定字符是否在该列表中,都返回 True 或 False。

这是我的代码:

def inlist(character, lists):
    """Checks if a given character is in a list of any level"""
    
    if lists[0] == character:
        return True
    
    elif isinstance(lists[0], list):
        return inlist(character,lists[0])
    
    elif not lists[0] == character:
        return inlist(character,lists[1:])
    
    else:
        return False

当我运行代码时:("c", [["a", "b","c", "d"],"e"])

它似乎工作正常。但是,当我以这种方式输入列表时: ("c", [["a", "b",],["c", "d"],"e"])

它给了我一个错误,上面写着:IndexError: list index out of range

我不能这样写嵌套列表吗?如果是这样,为什么? 还是我的代码有什么问题导致它无法通过整个列表?

【问题讨论】:

  • 在检查lists 是否有任何元素之前,请注意您的lists[0]
  • 嗯,如果我在上面加上另一个 if 语句并缩进其他所有内容会更好吗?
  • 我会把你当前的if 变成elif,然后将if 变成if not list: 之类的东西。无需嵌套。
  • 你的逻辑也有点缺陷,如果第一个元素是一个没有字符的列表,elif 将触发并返回 False,即使后面的列表可能返回 True。跨度>
  • @Wups 切片实际上在空列表上是安全的。这是一个不错的功能。

标签: python list recursion nested


【解决方案1】:

你写的有点复杂,而递归的思路应该简单很多

DFS 版本:

(你可以阅读更多关于 DFS 遍历全网的内容)

def inlist(character, lists):
    """Checks if a given character is in a list of any level"""
    for item in lists:
        if item==character:
            return True
        if isinstance(item, list):
            if inlist(character, item):
                return True
    return False
    
            
        
a = ["c", [["a", "b",],["c", "d"],"e"]]
print(inlist("a", a))

输出:

True

对于这个输入:

print(inlist("z", a))

输出是:

False

简短说明:

  • 遍历列表中的所有项目

  • 如果项目是角色 - 完成

  • 如果项目是列表 - 立即调用递归(这里吸引人的部分是仅在 True 时返回,因为如果不是 - 这并不意味着在其他项目中找不到该字符)

  • 如果完成所有项目但未找到 - 完成

  • 当项目有更多机会出现在内部列表中时会更好

BFS 版本:

(你可以在网上阅读更多关于 BFS 遍历的内容)

def inlist(character, lists):
    """Checks if a given character is in a list of any level"""
    extra_arr = []
    for item in lists:
        if item==character:
            return True
        if isinstance(item, list):
            extra_arr.append(item)
    
    for extra_item in extra_arr:
        if inlist(character, extra_item):
            return True
    return False

当然,结果相同。

简短说明:

  • 遍历列表中的所有项目

  • 如果项目是角色 - 完成

  • 如果项目是列表 - 附加到extra_arr,它将在验证当前级别中的所有项目后执行

  • 如果完成所有项目但未找到 - 完成

  • 当项目有更多机会出现在外部列表中时会更好

【讨论】:

  • 这似乎是一个更聪明、更简单的解决方案,我会记住的!我知道这是迭代和递归的混合。这是解决这些问题的常用方法吗?或者是否存在只首选递归的情况?
  • 我添加了一些 DFS 和 BFS 方法的更多“教育内容”,它主要来自图遍历,但在我看来,这里似乎是类似的情况。我不知道对于什么是“通常的方式”是否有任何明确的定义,我猜每个人都有自己的喜好,更重要的是,我认为递归和迭代之间没有关系。跨度>
【解决方案2】:

采用纯递归方法,就像问题中使用的那样:

def inlist(char, lists):
    if not lists: # check for empty list
        return False
        
    if lists[0] == char:
        return True

    elif isinstance(lists[0], list) and inlist(char, lists[0]):
        return True # return only if found in sublist, otherwise continue

    elif len(lists) > 1: # check rest of the list, if there is a rest
        return inlist(char, lists[1:])
        
    return False # all possibilities exhausted. Char not in this (sub-)list

这对于某些问题很有用,但要在列表中查找元素,循环会更快。此外,对于较长的列表,最大递归深度将是一个问题。

【讨论】:

    【解决方案3】:

    @Wups 为您提供了纯递归解决方案。很好地抓住了isinstance(lists[0], list) 的情况,如果递归调用返回false,您仍然必须小心检查lists[1]

    始终检查列表是否为空获取值之前。这是使用高阶函数(如some)来思考问题的另一种方法。

    def some(f, t):
      if not t:
        return False
      else:
        return f(t[0]) or some(f, t[1:])
    
    def inlist(char, ls):
      return some \
        ( lambda v: inlist(char, v) if isinstance(v, list) else char == v
        , ls
        )
    
    input = ["c", [["a", "b",],["c", "d"],"e"]]
    print(inlist("a", input))
    print(inlist("z", input))
    
    True
    False
    

    我们在上面写some 作为练习。你应该知道 Python 有一个内置的 any 函数 -

    def inlist(char, ls):
      return any(isinstance(v, list) and inlist(char, v) or char == v for v in ls)
    
    input = ["c", [["a", "b",],["c", "d"],"e"]]
    print(inlist("a", input))
    print(inlist("z", input))
    
    True
    False
    

    【讨论】:

      猜你喜欢
      • 2014-03-06
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 2021-08-15
      • 1970-01-01
      • 2016-08-16
      • 2021-09-19
      • 1970-01-01
      相关资源
      最近更新 更多