#python #recursion #nested-lists
#python #рекурсия #вложенные списки
Вопрос:
Я борюсь с упражнением в течение нескольких дней. Задан следующий вложенный список:
[1, [5, 62, 6], 4, [99, [100, 200, 600, [1000, [2000]]]], [74, 41, 16], 7, [8], [[[400]]]]
И это тело функции:
def find_element(liste, find, index = 0):
Мне нужно найти элемент во вложенном списке, и функция должна возвращать точный индекс найденного элемента, например [1,0] для 5 или [3, 1, 3, 1, 0] за 2000 год.
Функция должна быть рекурсивной.
Моя проблема в том, что функция должна возвращать false, если элемента нет в списке.
Это мой код:
def find_element(liste, find, index = 0):
indexList = []
if len(liste) == index:
return indexList
if liste[index] == find:
indexList.append(index)
else:
if type(liste[index]) == list:
indexList.extend(find_element(liste[index], find))
if indexList:
indexList.insert(0, index)
else:
indexList.extend(find_element(liste, find, index 1))
return indexList
Я попробовал вторую функцию, которая возвращает false, когда список пуст, или условие if, если индекс равен 0, а список индексов пуст, но все, что я получил, это ошибка рекурсии или ошибка типа.
Ответ №1:
Ответ Ajax1234 работает, но если вам нужно что-то более простое, это может быть лучше:
def find_idx(input_list, elem):
for i in range(len(input_list)):
if isinstance(input_list[i], list):
result = find_idx(input_list[i], elem)
if result:
return [i] result
elif input_list[i] == elem:
return [i]
return False
input_list = [1, [5, 62, 6], 4, [99, [100, 200, 600, [1000, [2000]]]], [74, 41, 16], 7, [8], [[[400]]]]
print(find_idx(input_list, 2000))
# Output: [3, 1, 3, 1, 0]
По сути, это DFS (https://en.wikipedia.org/wiki/Depth-first_search ). Если вы представляете свою структуру данных как дерево, записи вашего списка являются узлами, поскольку они сами могут содержать другие списки, точно так же, как узел в дереве может указывать на другие узлы. Волшебство заключается в возврате False
, если ничего не было найдено в самом конце метода, но рекурсивный поиск по всем подспискам, прежде чем вы дойдете до этой точки. Кроме того, вы должны проверить, является ли ваша запись списка сама по себе списком, но это всего лишь аналогия с тем фактом, что в дереве могут быть узлы, которые указывают на другие узлы, и узлы, которые этого не делают (конечные узлы или простые старые числа в вашем случае).
Ответ №2:
Вы можете использовать рекурсию с генератором:
def find_element(l, elem):
def get_elem(d, c = []):
for i, a in enumerate(d):
if a == elem:
yield c [i]
elif isinstance(a, list):
yield from get_elem(a, c [i])
return False if not (r:=list(get_elem(l))) else r[0]
data = [1, [5, 62, 6], 4, [99, [100, 200, 600, [1000, [2000]]]], [74, 41, 16], 7, [8], [[[400]]]]
print(find_element(data, 2000))
Вывод:
[3, 1, 3, 1, 0]
Ответ №3:
Я согласен, что генераторы хорошо подходят для этой проблемы. Я бы разделил логику программы на две отдельные функции dfs
и find_element
—
def dfs(ls, r = []):
if isinstance(ls, list):
for (i, v) in enumerate(ls):
yield from dfs(v, [*r, i])
else:
yield (r, ls)
def find_element(ls, q):
for (k, v) in dfs(ls):
if v == q:
return k
return None
print(find_element(input, 5))
# [1, 0]
print(find_element(input, 2000))
# [3, 1, 3, 1, 0]
print(find_element(input, 999))
# None
Или вы могли бы исправить свою исходную программу, используя четвертый параметр, r = []
—
def find_element(ls, q, i = 0, r = []):
if i >= len(ls):
return None
elif isinstance(ls[i], list):
return find_element(ls[i], q, 0, [*r, i])
or find_element(ls, q, i 1, r)
elif ls[i] == q:
return [*r, i]
else:
return find_element(ls, q, i 1, r)
print(find_element(input, 5))
# [1, 0]
print(find_element(input, 2000))
# [3, 1, 3, 1, 0]
print(find_element(input, 999))
# None