嵌套列表中元素的索引

Index of an element in a nested list

这几天我一直在努力锻炼。 给出的是以下嵌套列表:

[1, [5, 62, 6], 4, [99, [100, 200, 600, [1000, [2000]]]], [74, 41, 16], 7, [8], [[[400]]]]

还有这个函数体:

def find_element(liste, find, index = 0):

我必须在嵌套列表中找到一个元素,函数应该 return 找到的元素的确切索引,例如 [1,0] 表示 5 或 [3, 1, 3, 1 , 0] 为 2000。 该函数必须是递归的。

我的问题是如果元素不在列表中,函数必须 return 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

我尝试了第二个函数,当列表为空时 returns false 或如果索引为 0 且 indexList 为空时的 if 条件,但我得到的只是 RecursionError 或 TypeError。

您可以对生成器使用递归:

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]

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,但在到达该点之前递归搜索所有子列表。此外,您必须检查您的列表条目本身是否是一个列表,但这只是一个类比,即一棵树可以具有指向其他节点的节点和不指向其他节点的节点(叶节点或普通旧数字)在你的情况下)。

我同意生成器非常适合这个问题。我会将程序逻辑分成两个单独的函数,dfsfind_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