Python中的递归列表切片

时间:2019-05-08 23:39:20

标签: python recursion

我正在拼接给定列表中不需要的部分,我想递归地进行操作。我正在努力寻找基于一组令牌删除某些内容的正确方法。例如,如果我有['a','b','c','d','e'],则尝试将其从'b'递归删除到'd',这将导致['a','e']

这是迄今为止最接近我的地方。

lines = """
variable "ops_manager_private" {
  default     = false
  description = ""
}

variable "optional_ops_manager" {
  default = false
}

/******
* RDS *
*******/

variable "rds_db_username" {
  default = ""
}

variable "rds_instance_class" {
  default = ""
}

variable "rds_instance_count" {
  type    = "string"
  default = 0
}
"""

def _remove_set(target: list, start: str, stop: str, delete=False):
    if not target:
        return []
    elif target[0] == start:
        return target[0] + _remove_set(target[1:], start, stop, delete=True)
    elif delete is True:
        return _remove_set(target[1:], start, stop, delete=True)
    elif target[0] == stop:
        return target[0] + _remove_set(target[1:], start, stop, delete=False)
    else:
        return target[0] + _remove_set(target[1:], start, stop, delete=False)


if __name__ == __main__:
    results = _remove_set(lines.splitlines(), 'ops_', '}\n')    

然后我得到这个错误:

Traceback (most recent call last):
# large recursive traceback
TypeError: can only concatenate str (not "list") to str

递归切片列表的正确方法是什么?

4 个答案:

答案 0 :(得分:1)

您可以使用循环在开始标记“ b”和结束标记“ d”之间跳过元素:

items=['a','b','c','d','e']
result=[]
skip=False

for item in items:
    if item == 'b':
        skip = True
    elif not skip:
        result.append(item)
    elif item == 'd':
        skip = False

print(result)
# ['a', 'e']

答案 1 :(得分:1)

通常,递归方法将查看一个元素,然后将其余元素传递回该函数。如果执行此操作,则只需确定是否要包含一个元素+递归结果。像这样:

def remove(arr, delete):
    ''' remove element from arr in in delete list'''
    if not arr:    # edge condition
        return arr
    n, *rest = arr 

    if n in delete:
        return remove(rest, delete)
    else:
        return [n] + remove(rest, delete)

l = ['a','b','c','d','e']

remove(l, ['d', 'b'])

答案 2 :(得分:0)

您可以将生成器与itertools.takehwile配合使用,以产生不在开始/停止标记之间的元素:

import itertools as it

def remove(items, start, stop):
    items = iter(items)
    while True:
        yield from it.takewhile(start.__ne__, items)
        if all(x != stop for x in items):
            break

print(list(remove('abcde', 'b', 'd')))  # ['a', 'e']
print(list(remove('abcdefbghdi', 'b', 'd')))  # ['a', 'e', 'f', 'i']

答案 3 :(得分:0)

对于递归解决方案,您可以使用(list|str|tuple).index方法,而不是一个一个地遍历元素:

def remove(items, start, stop):
    try:
        i = items.index(start)
        j = items.index(stop, i)
    except ValueError:
        return items[:]
    return items[:i] + remove(items[j+1:], start, stop)

print(remove('abcde', 'b', 'd'))  # 'ae'
print(remove('abcdefbghdi', 'b', 'd'))  # 'aefi'

请注意,这只会删除显式关闭部分中的项目,即末尾不会隐式关闭:

print(remove('abc', 'b', 'd'))  # 'abc'