【问题标题】:Recursive function to find the levels of elements in list递归函数查找列表中元素的级别
【发布时间】:2019-12-04 09:00:59
【问题描述】:

我需要编写一个递归函数,它从原始列表返回一个列表,其中每个元素都由该级别的元素组成。例如[1, [2, [3], [[4], 3], 2], 1, []] 该列表的结果应该是[[1, 1], [2, 2], [3, 3], [4]](元素 1、1 在级别 1,元素 2、2 在级别 2 等)。另一个例子是[8, [6, 7, [-1], [4, [[10]]], 2], 1] 变成[[8, 1], [6, 7, 2], [-1, 4], [], [10]]。我试图遍历每个元素,当它不是列表时,将元素添加到结果中。否则我再次调用该函数,直到我再次到达一个元素。但问题是它只是将所有元素添加到结果中。我被卡住了,真的不知道如何继续。

def levels(x, level = 0, result = []):
    for element in x:
        if type(element) is not list:
            result.append(element)
        else:
            levels(element, level + 1, result)

    return result

print(levels([1, [2, [3], [[4], 3], 2], 1, []]))
print(levels([8, [6, 7, [-1], [4, [[10]]], 2], 1]))

我的结果:

[1, 2, 3, 4, 3, 2, 1]
[1, 2, 3, 4, 3, 2, 1, 8, 6, 7, -1, 4, 10, 2, 1]

应该是什么:

[[1, 1], [2, 2], [3, 3], [4]]
[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

非常感谢任何帮助。

【问题讨论】:

  • Idk 如果这是您的问题,但您绝对应该修复 result = [] 参数。见here。不要将可变对象作为默认参数,除非你从不改变它。

标签: python recursion


【解决方案1】:

你可以使用递归itertools.groupby:

from itertools import groupby as gb
data = [1, [2, [3], [[4], 3], 2], 1, []] 
def get_levels(d, c=0):
  yield (c, [])
  for i in d:
     yield from ([(c, i)] if not isinstance(i, list) else get_levels(i, c+1))

r = [list(b) for _,b in gb(sorted(get_levels(data), key=lambda x:x[0]), key=lambda x:x[0])]
result = [list(filter(lambda x:x != [], [k for _, k in b])) for b in r]

输出:

[[1, 1], [2, 2], [3, 3], [4]]

输入测试 2:

data = [8, [6, 7, [-1], [4, [[10]]], 2], 1]
...

输出:

[[8, 1], [6, 7, 2], [-1, 4], [], [10]]

【讨论】:

  • 谢谢!感谢您的帮助!
【解决方案2】:

这个解决方案非常明确,可以简化和避免一些参数。

它通过引用子列表来工作

def levels(my_list, index=0, new_list=None):
    if new_list is None:
        new_list = []

    if len(new_list) > index:
        items = new_list[index]
    else:
        items = []
        new_list.append(items)

    for item in my_list:
        if isinstance(item, list):
            nex_index = index + 1
            levels(item, nex_index, new_list)
        else:
            items.append(item)

    return new_list

运行:

> print(levels([8, [6, 7, [-1], [4, [[10]]], 2], 1]))
> [[8, 1], [6, 7, 2], [-1, 4], [], [10]]

> print(levels([1, 1, [], [2, 2, [3], [3, [4]]]]))
> [[1, 1], [2, 2], [3, 3], [4]]

【讨论】:

  • 考虑添加一个关于您尝试在解决方案中做什么的简短介绍。很有帮助!
  • 谢谢!感谢您的帮助!
  • 很好的答案(赞成)。我们可以在没有额外参数的情况下获得更纯粹的递归(见我的回答)。
【解决方案3】:

递归通常意味着从后面的调用返回的值的类型与前面的调用相同,而后者建立在前者之上。因此,在这种情况下,如果我们在新级别上调用该函数,我们将获得一个列表,其第一个元素表示比当前级别更深的级别。

def f(lst):
  result = [[]]
  deeper_res = []

  for e in lst:
    if isinstance(e, list):
      deeper = f(e)
      k = max(0, len(deeper) - len(deeper_res))
      deeper_res = [a + b for a,b in zip(deeper_res + [[]] * k, deeper)]
    else:
      result[0].append(e)

  return result + deeper_res

print(f([8, [6, 7, [-1], [4, [[10]]], 2], 1]))
# [[8, 1], [6, 7, 2], [-1, 4], [], [10]]
print(f([1, 1, [], [2, 2, [3], [3, [4]]]]))
#[[1, 1], [2, 2], [3, 3], [4]]

【讨论】:

  • 谢谢!感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2018-06-13
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 2016-11-26
  • 2016-06-28
相关资源
最近更新 更多