如何递归创建列表?
我有此列表:
l = ['a', 'b', 'new', 'c', 'd', 'new', 'z', 'x', 'c', 'fin', 'f', 'fin',
'g', 'l', 'new', 'z', 'x', 'c', 'fin', 'j']
预期输出为:
r = ['a', 'b', ['c', 'd', ['z', 'x', 'c'] 'f'], 'g', 'l', ['z', 'x', 'c'] 'j']
到目前为止,我已经尝试过:
def asd(l, index=0):
r = []
for i in l[index:]:
index += 1
if i == 'new':
i, index = asd(l, index)
r.append(i)
if i == 'fin':
return r
return r, index
r, index = asd(l)
我不明白如何使其工作。谁能帮我吗?
答案 0 :(得分:2)
这是一种非递归解决方案,可以创建列表,一次性解析,而无需进行昂贵的index()
操作:
l = ['a', 'b', 'new', 'c', 'd', 'new', 'f', 'fin', 'g', 'fin', 'j']
rv = []
curr = [rv] # things are always added to the last element if not 'fin' or 'new'
for elem in l:
if elem == "new":
# create a new list, put it at end of curr
curr.append([])
# add that list to the one before
curr[-2].append(curr[-1])
elif elem == "fin":
# done, remove from curr
curr.pop()
else:
curr[-1].append(elem)
print(rv)
输出:
['a', 'b', ['c', 'd', ['f'], 'g'], 'j']
l = ['a', 'b', 'new', '1', '2', '3', 'fin', 'c', 'new', 'x', 'y', 'z', 'fin',]
导致
['a', 'b', ['1', '2', '3'], 'c', ['x', 'y', 'z']]
您需要万无一失,以防不平衡/错误的new
/ fin
的
经过编辑,使其在Matthieu的评论后更加简洁。
答案 1 :(得分:2)
这是一种简单的递归解决方案,使用deque
作为堆栈数据结构,可以从其中popleft
from collections import deque
def nest(lst):
return _nest(deque(lst))
def _nest(deq):
result = []
while deq:
x = deq.popleft()
if x == 'fin':
break
elif x == 'new':
result.append(_nest(deq))
else:
result.append(x)
return result
O(1)中最左边的元素。
算法
tests = [
[],
[1, 2, 3],
[1, 2, 'new', 3, 4, 'fin', 5],
[1, 2, 'new', 3, 4, 'fin', 5, 6, 'new', 7, 'fin'],
['new', 'fin', 'new', 'fin', 'new', 'new', 'fin', 'fin'],
['new', 1, 2, 'fin'],
[1, 2, 3, 'new', 4, 'new', 5, 6, 'fin', 7, 8, 'fin', 9, 10, 'new', 11, 'fin', 12, 13]
]
for test in tests:
print(nest(test))
测试
[]
[1, 2, 3]
[1, 2, [3, 4], 5]
[1, 2, [3, 4], 5, 6, [7]]
[[], [], [[]]]
[[1, 2]]
[1, 2, 3, [4, [5, 6], 7, 8], 9, 10, [11], 12, 13]
输出
.useXpath() // every selector now must be XPath
.click("//a[text()='Two']")
.useCss() // we're back to CSS now
答案 2 :(得分:1)
您可以改用堆栈,并遍历列表并使用它:
def parse(l):
stack = [[]]
for i in l:
if i == "new":
stack.append([])
elif i == "fin":
pop = stack.pop()
stack[-1].append(pop)
else:
stack[-1].append(i)
return stack[0]
答案 3 :(得分:1)
递归替代:
def asd(l):
if 'new' in l:
index_new = l.index('new')
keyword = 1
for index_fin,e in enumerate(l[index_new+1:], index_new+1):
if e == 'new':
keyword += 1
elif e == 'fin':
keyword -=1
if not keyword:
break
return l[:index_new] + [asd(l[index_new+1:index_fin])] + asd(l[index_fin+1:])
else:
return l
输入:
['a', 'b', 'new', 'c', 'd', 'new', 'z', 'x', 'c', 'fin', 'f', 'fin',
'g', 'l', 'new', 'z', 'x', 'c', 'fin', 'j']
输出:
['a', 'b', ['c', 'd', ['z', 'x', 'c'], 'f'], 'g', 'l', ['z', 'x', 'c'], 'j']