【问题标题】:Python: How to search a nested list using recursionPython:如何使用递归搜索嵌套列表
【发布时间】:2016-01-31 18:47:13
【问题描述】:

我正在尝试使用 python 搜索嵌套列表。例如,函数为nestedListContains(NL, target)nestedListContains([1, [2, [3], 4]], 3) 应该返回 TruenestedListContains([1, [2, [3], 4]], 5) 应该返回 False

我尝试了什么:

def nestedListContains(NL, target):
   if target not in NL:
      return False
   else:
      return True

我给出的示例有效,但如果它是 nestedListContains([[9, 4, 5], [3, 8]], 3) 那么它给了我错误的返回值。我该如何解决这个问题?

【问题讨论】:

    标签: python list python-3.x


    【解决方案1】:

    这样的?

    def nested_list_contains(nl, target):
        for thing in nl:
            if type(thing) is list:
                if nested_list_contains(thing, target):
                    return True
            if thing == target:
                return True
        return False
    
    print(nested_list_contains([1, [2, [3], 4]], 3))  # True
    print(nested_list_contains([1, [2, [3], 4]], 5))  # False
    

    【讨论】:

    • 我认为你应该检查 NL 是否是一个列表而不是目标长度。
    • 它给了我一个'int'类型的错误对象没有长度
    【解决方案2】:

    这几乎是完美的,但递归在哪里?

    def nestedListContains(NL, target):
       if target not in NL:
          return False # <-- HINT: hint, it should be here
       else:
          return True
    

    not in 检查只检查最高级别的嵌套。

    试试这样的:

    from collections import Iterable
    
    def nestedListContains(NL, target):
       if target not in NL:
          if isinstance(NL, Iterable):
              for sub in NL:
                  return nestedListContains(sub, target)
          else:
              return False
       else:
          return True
    

    使用Iterable 的检查应该可以使其与set 等其他可迭代类一起工作。

    【讨论】:

      【解决方案3】:

      以下算法具有线性运行时复杂度。与this 不同的是,结果仅在一次传递中找到:

      def search(l, target):
          for element in l:
              if isinstance(element, list) and search(element, target):
                  return True
              if target == element:
                  return True
          return False
      

      【讨论】:

      • 这里的两个答案都具有线性运行时复杂度?
      • 这在@Filip Haglund 编辑他的答案之前是正确的。
      • 不,它没有。旧版本最多进行两次线性传递;仍然是 O(n)。我很难想出一种方法来编写更慢的搜索算法。
      • 在嵌套列表的情况下,您之前的解决方案需要两次传递。仍然是线性的,但通过了两次。
      • 查看所有答案。它们都是 O(n)。我们的答案非常相似。您的回答绝对不是“与此处发布的其他解决方案不同”。
      【解决方案4】:

      我更喜欢使用isinstance(nl, list),而不是使用type(nl) is list,以获得更通用的算法,允许子类化。

      def nl_contains(nl, target):
          return isinstance(nl, list) and \
                 any(item == target or nl_contains(item, target) for item in nl)
      

      这里有一些测试:

      >>> nl_contains([1, 2, 3], 1)
      True
      >>> nl_contains([1, 2, 3], 4)
      False
      >>> nl_contains([1, [2], 3], 2)
      True
      >>> nl_contains([1, [2], 3], 4)
      False
      >>> nl_contains([["ab"], ["cd"]], "a")
      False
      >>> nl_contains([["ab", [1, 2]], ["cd"]], [1, 2])
      True
      >>> nl_contains([["ab", [1, 2]], ["cd"]], [1, [2]])
      False
      

      如果你想检查子类:

      >>> class MyList(list):
      ...    pass
      
      >>> nl_contains(MyList(xrange(3)), 2)
      True
      

      在 Python 中,我们使用可迭代对象(listsetdict)或生成器对象。

      要检查对象是否可迭代,请使用:hasattr(iterable, '__iter__')

      例如:

      def iterable_contains(iterable, target):
          return hasattr(iterable, '__iter__') and \
                 any(item == target or iterable_contains(item, target) for item in iterable)
      

      一些单元测试:

      >>> iterable_contains([1, 2, 3], 1)
      True
      >>> iterable_contains([1, 2, 3], 4)
      False
      >>> iterable_contains([1, [2], 3], 2)
      True
      >>> iterable_contains([1, [2], 3], 4)
      False
      >>> iterable_contains([["ab"], ["cd"]], "a")
      False
      >>> iterable_contains([["ab", [1, 2]], ["cd"]], [1, 2])
      True
      >>> iterable_contains([["ab", [1, 2]], ["cd"]], [1, [2]])
      False
      
      >>> class MyList(list):
      ...    pass
      >>> iterable_contains(MyList(xrange(3)), 2)
      True
      
      >>> iterable_contains({1, 3, (5, 6), 7, 9}, (5,6))
      True
      >>> iterable_contains(dict(a=5, b=9), 'a')
      True
      >>> iterable_contains(xrange(10), 5)
      True
      >>> iterable_contains(xrange(10), 10)
      False
      

      【讨论】:

        【解决方案5】:
        def findX(l, x):
          if(x in l):
             return True
          # whenever we got a list explore it
          for i in l: # this part will recursively check lists (Depth First Search)
             if(type(i)==list):
                out = findX(i, x) # use recursion here
                if(out==True):# we only need Return  True from inner Lists
                   return True
                        #if not true go for the next list
          return False
        

        【讨论】:

        • 可用于使用递归在多重嵌套列表中查找 x
        猜你喜欢
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-15
        • 2012-04-12
        • 2018-07-19
        相关资源
        最近更新 更多