在大型子列表树中查找特定值
Find a specific value in a large tree of sublists
我有一些代码可以生成如下所示的列表:
chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]
现在我需要在类似这样的列表中找到特定值。
我写了一些代码来做到这一点,但它似乎陷入了无限循环:
def locate_value(v,chrs): #
checked=[[]] # Set up the values
index_list=[] #
inside=0 #
cur=[0,0] #
#
while True: #
if chrs[cur[0]] == v: # If found, end the loop and return the index_list
return index_list #
#
if type(chrs[cur[0]]) != list: # If the current is not a list, skip this one
checked[inside].append(cur[0]) #
index_list = [] #
#
else: #
try: #
if cur[0] in gone[inside]: # If the current has been done before, skip it
cur[0] += 1 #
#
else: # And if not, move 1 space deeper
checked.append([]) #
index_list.append(cur[0]) #
cur[1] = cur[0] #
cur[0] = 0 #
inside += 1 #
#
except IndexError: # And if a sublist is fully checked, block it too
checked[inside].append(cur[1]) #
print(locate_value("e",[[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]))
Editing me just realised how bad this code is
在这个例子中,函数 locate_value
应该 return [0, 1, 1]
,因为 list[0][1][1]
是 "e"
但是当我运行这个的时候,我陷入了一个无限循环
任何人都可以告诉我哪里出了问题,也许可以给我一些实际上 有效 一次的代码。
这个列表是用户输入的,所以我不知道它有多深。
虽然仅 python-3 的解决方案很好,但我更喜欢支持 python-2 的解决方案。
以下将起作用:
def locate_value(v, chrs):
if v == chrs:
return []
if not isinstance(chrs, list):
raise IndexError
for i, c in enumerate(chrs):
try:
return [i] + locate_value(v, c)
except IndexError:
pass
raise IndexError
locate_value("e", [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]])
# [0, 1, 1]
请注意,str
对象本身就是可迭代对象,因此递归地不断迭代它们的元素(再次是字符串)将永远不会结束。
使用递归函数:
def locate_value(v, chrs, idx=[]):
for j, i in enumerate(chrs):
if isinstance(i, list):
yield from find(v, i, idx + [j])
elif i == v:
yield idx + [j]
保留您原有签名功能的另一个版本:
def locate_value(v, chrs):
for j, i in enumerate(chrs):
if isinstance(i, list):
yield from ([j, *idx] for idx in locate_value(v, i))
elif i == v:
yield [j]
输出:
>>> list(locate_value('e', chrs, []))
[[0, 1, 1]]
# case of multiple 'e'
# chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","e"],"j"]]]
>>> list(locate_value('e', chrs))
[[0, 1, 1], [1, 1, 0, 1]]
大大改进@tobias_k
我有一些代码可以生成如下所示的列表:
chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]
现在我需要在类似这样的列表中找到特定值。
我写了一些代码来做到这一点,但它似乎陷入了无限循环:
def locate_value(v,chrs): #
checked=[[]] # Set up the values
index_list=[] #
inside=0 #
cur=[0,0] #
#
while True: #
if chrs[cur[0]] == v: # If found, end the loop and return the index_list
return index_list #
#
if type(chrs[cur[0]]) != list: # If the current is not a list, skip this one
checked[inside].append(cur[0]) #
index_list = [] #
#
else: #
try: #
if cur[0] in gone[inside]: # If the current has been done before, skip it
cur[0] += 1 #
#
else: # And if not, move 1 space deeper
checked.append([]) #
index_list.append(cur[0]) #
cur[1] = cur[0] #
cur[0] = 0 #
inside += 1 #
#
except IndexError: # And if a sublist is fully checked, block it too
checked[inside].append(cur[1]) #
print(locate_value("e",[[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]))
Editing me just realised how bad this code is
在这个例子中,函数 locate_value
应该 return [0, 1, 1]
,因为 list[0][1][1]
是 "e"
但是当我运行这个的时候,我陷入了一个无限循环 任何人都可以告诉我哪里出了问题,也许可以给我一些实际上 有效 一次的代码。
这个列表是用户输入的,所以我不知道它有多深。
虽然仅 python-3 的解决方案很好,但我更喜欢支持 python-2 的解决方案。
以下将起作用:
def locate_value(v, chrs):
if v == chrs:
return []
if not isinstance(chrs, list):
raise IndexError
for i, c in enumerate(chrs):
try:
return [i] + locate_value(v, c)
except IndexError:
pass
raise IndexError
locate_value("e", [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]])
# [0, 1, 1]
请注意,str
对象本身就是可迭代对象,因此递归地不断迭代它们的元素(再次是字符串)将永远不会结束。
使用递归函数:
def locate_value(v, chrs, idx=[]):
for j, i in enumerate(chrs):
if isinstance(i, list):
yield from find(v, i, idx + [j])
elif i == v:
yield idx + [j]
保留您原有签名功能的另一个版本:
def locate_value(v, chrs):
for j, i in enumerate(chrs):
if isinstance(i, list):
yield from ([j, *idx] for idx in locate_value(v, i))
elif i == v:
yield [j]
输出:
>>> list(locate_value('e', chrs, []))
[[0, 1, 1]]
# case of multiple 'e'
# chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","e"],"j"]]]
>>> list(locate_value('e', chrs))
[[0, 1, 1], [1, 1, 0, 1]]
大大改进@tobias_k