Как получить индексы элемента вложенного списка из n измерений - PullRequest
1 голос
/ 01 июня 2019

Я новичок в Python (программирование в целом), и у меня есть некоторые проблемы, которые я не знаю, как обойти.У меня есть много разных вложенных списков, следующих этому шаблону:

Listi = [string0, string1, ..., stringn, [list0], [list1], ..., [listn]]

(Список содержит количество строк, всегда расположенных в начале, продолжаемых числом списков, всегда расположенных после).

Списки, содержащиеся в первом списке, имеют такую ​​же точную структуру, что и первый список.Списки могут иметь любое количество списков внутри них.

То, что я хотел бы закодировать, - это функция, которая с помощью случайного элемента (случайной строки) находит индексы такого элемента внутри списка, чтобы этот элемент могбыть вызванным из основного списка, который содержит его.

Я хотел бы получить наилучший возможный способ выполнить это с точки зрения количества операций, но любое решение вообще было бы очень цениться.

Вот некоторый пример: представьте, что у меня есть два списка:

l1 = ['Node_50', ['Node_48', 'Node_23'], ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]
l2 = ['Node_50', ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']], ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]

Я хотел бы получить такую ​​функцию:

def functionfinder(list, element):

такую, что:

indexes = functionfinder(l1, "Node_40")

индексы будут кортежем (2, 2, 1), потому что:

l1[2][2][1] = Node_40

1 Ответ

0 голосов
/ 01 июня 2019

Поскольку вы ищете вложенные списки, лучше всего использовать рекурсивную процедуру.Поскольку вам нужна хорошая скорость, процедура должна завершиться, как только будет найден нужный элемент (вместо продолжения поиска или поиска другого).Следующее должно работать, если вы фактически используете только списки в качестве контейнеров для ваших строк.

def functionfinder(asequence, value, indexes_tuple=()):
    for ndx, item in enumerate(asequence):
        if item == value:  
            return indexes_tuple + (ndx,) # found it here: return the answer
        if isinstance(item, list):
            result = functionfinder(item, value, indexes_tuple + (ndx,))
            if result:  
                return result # found it below: stop looking for it
    return ()  # desired value not found yet

l1 = ['Node_50',
      ['Node_48', 'Node_23'],
      ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]
     ]
l2 = ['Node_50',
      ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']],
      ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]
     ]

indexes = functionfinder(l1, "Node_40")
print(indexes)

Распечатка из этого кода - то, что вы хотите:

(2, 2, 1)

Если у вас есть indexes и вы хотите получить доступ к искомому значению, вы можете сделать

result = l1
for ndx in indexes:
    result = result[ndx]

Теперь result содержит искомое значение.

Этот код может быть обобщен для обработки другихвиды последовательностей, такие как кортежи, а не просто списки.Вы должны быть осторожны, чтобы не возвращаться в строку, поскольку строки Python также являются последовательностями символов.Вы хотите кортеж в качестве возвращаемого значения, поэтому мой код также использует их.Использование неизменяемого типа в качестве возвращаемого значения имеет свои преимущества.Но использование изменяемого типа, такого как список, может ускорить скорость выполнения.Как и сейчас, каждый новый список в вашем параметре требует создания полного нового набора индексов.Использование списка может означать, что вам просто нужно добавить один новый индекс и может ускорить код.Спросите, подходит ли вам какое-либо из этих возможных улучшений.

Обратите внимание, что, поскольку у Python нет встроенного немедленного способа остановки рекурсивной функции, мой код использует возвращенный пустой кортеж, чтобы отметить, что требуемый элементеще не был найден.Когда элемент найден, возвращается непустой кортеж, который сигнализирует о том, что все уровни рекурсии должны быть остановлены как можно скорее.Это несколько усложняет код.

...