如何深度搜索 Python 列表?
Posted
技术标签:
【中文标题】如何深度搜索 Python 列表?【英文标题】:How can I deep search a Python list? 【发布时间】:2013-02-23 22:22:42 【问题描述】:我想在 Python 中的列表中进行深度搜索。比如我想知道5在my_list
中与否。
my_list = [2, [3, 4, [2, 3]], 1, [4, [5]]]
我该怎么做?
【问题讨论】:
【参考方案1】:不确定使用多层嵌套的快速方法,但是像这样的递归算法可以解决问题:
def nestedSearch(nested, v):
for element in nested:
if isinstance(element, list):
if nestedSearch(element, v):
return True
elif element == v:
return True
return False
你也可以看看这个扁平化多嵌套列表:
Recursive generator for flattening nested lists
【讨论】:
【参考方案2】:您可以将flatten
function(将其视为itertools.chain
的递归版本)与Python 的标准in
运算符(在生成器上进行线性搜索)结合起来得到:
>>> def flatten(nested):
try:
for sublist in nested:
for element in flatten(sublist):
yield element
except TypeError:
yield nested
>>> my_list = [2, [3, 4, [2, 3]], 1, [4, [5]]]
>>> 5 in flatten(my_list)
True
根据链接问题中的 cmets,如果您要搜索的内容是可迭代的,您将需要优化 flatten
代码 - 例如,元组将像列表一样被展平到搜索中,并且搜索字符串递归直到它达到了 Python 的堆栈限制。
【讨论】:
【参考方案3】:如果你有一个列表列表,你可以使用这种方法
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> [item for sublist in l for item in sublist]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 5 in [item for sublist in l for item in sublist]
True
首先将列表展平,然后使用 O(n) 进行搜索。
如果你的列表看起来像你的例子,我想不出另一种方法来 这样做比使用 for 循环...
【讨论】:
这仅在您正在展平一个级别的列表时才有效,并且每个元素都保证是可迭代的并且不是搜索的可能匹配项。在这种情况下,5 in itertools.chain.from_iterable(l)
可能比列表推导更清晰,当然也更快(因为它不会构建仅用于一次搜索的完整列表)。
这就是我说的(或打算说的 :-) 见***.com/questions/952914/…
请注意,该问题的已接受答案中的 cmets 声称 list(itertools.chain.from_iterable(l)
比列表理解更快。您实际上并不需要一个列表来进行搜索(in
在任何可迭代对象上都可以正常工作)这一事实只会复合。【参考方案4】:
一种方法:
def deapSearch(searchElement, searchList):
for element in searchList:
if element == searchElement:
return True
elif type(element) == type(list):
found = deapSearch(searchElement, element)
if found:
return found
return False
deapSearch(5, my_list)
True
deapSearch(4, my_list)
True
不漂亮但工作。
【讨论】:
【参考方案5】:我最近需要这样做并且需要一个简单的解决方案。所以我将它添加为一种快速而肮脏的方式来展平/搜索列表(可能不是一个完美的解决方案,但它对我有用)。
>>> my_list = [2, [3, 4, [2, 3]], 1, [4, [5]]]
>>> str(5) in str(my_list) # returns True
>>> str(my_list).find(str(5)) # returns the index
编辑:也添加一个正则表达式解决方案。但是如果你有更复杂的情况,那么你不妨遍历列表。
>>> import re
>>> str(5) in re.findall('(?<=[,\[])([ a-zA-Z0-9 ]+)(?=[,\]])', str(my_list))
正则表达式本质上是扁平化列表,但不适用于列表项中的特殊字符。
【讨论】:
str(5) in str([1, [2, 15]]) # => True
你的方法不对。你至少需要一个正则表达式。【参考方案6】:
如果您只有一个包含整数或字符的嵌套列表,解决此问题的一种方法是创建一个没有所有不需要元素的列表(没有 '[' , ']' ...):
假设我们有一个带有字符的嵌套列表:
>>> nested = [[[[['F', 'B'], 'G'], ['D', 'A']], 'C'], 'E']
>>> string = str(nested)
>>> string = string.replace('[','',len(string))
>>> string = string.replace(']','',len(string))
>>> string = string.replace("'","",len(string))
>>> string = string.replace(" ","",len(string))
>>> string = string.split(',')
它给出了:
>>> print (string)
['F', 'B', 'G', 'D', 'A', 'C', 'E']
现在您可以轻松搜索,无需任何循环:
>>> 'F' in string
True
【讨论】:
您必须考虑的一件事是整数嵌套列表在内存中比简单字符串更昂贵,并且由于迭代,递归函数不是处理此类问题的最简单方法深度限制。使用 Python 的一大优势是您可以像在列表中搜索一样在字符串中搜索以上是关于如何深度搜索 Python 列表?的主要内容,如果未能解决你的问题,请参考以下文章
Python算法-深度优先搜索&广度优先搜索(DFS&BFS)