рекурсивно разделить список на подсписки на основе длины первого элемента - PullRequest
0 голосов
/ 06 мая 2020

Я ломаю себе голову над этой маленькой проблемой, которую, я уверен, можно (и нужно) решить рекурсивно.

# split list in sublists based on length of first element. 
list = [3, 1, 2, 3, 4, 1, 2, 3, 4]
       #*          #*

# *number of elements of the sublist    

Это лучше показано, чем объяснено, приведенное выше должно привести к:

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

Списки, которые я обрабатываю, всегда соблюдают это logi c, первым элементом всегда является длина следующих n элементов.

EDIT:

Основываясь на некоторых предложениях, я просто добавил yield, чтобы сделать это лениво.

def split(ls):
    """
    func that given a list extracts sub lists with the length indicated by the first element
    [2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4] => [[1, 2], [1, 2, 3], [1, 2, 3, 4]]
    """
    res = []
    while ls:
        dim = ls[0]
        yield ls[1:dim + 1]
        ls = ls[dim + 1:]

    return res

>>> list(split([2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4]))
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]

Ответы [ 4 ]

5 голосов
/ 06 мая 2020

Подойдет простая нарезка:

>>> a = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> c = []
>>> while len(a) :
...     b = a[0]
...     c.append( a[1:b+1] )
...     a = a[b+1:]
... 
>>> c
[[1, 2, 3], [1, 2, 3, 4]]
2 голосов
/ 06 мая 2020

Здесь вы можете использовать itertools.islice.

>>> from itertools import islice
>>> lst = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> def chunks(lst):
...     t=iter(lst)
...     c=next(t,None)
...     while c:
...             yield list(islice(t,None,c))
...             c=next(t,None)
...
>>> list(chunks(lst))
[[1, 2, 3], [1, 2, 3, 4]]
2 голосов
/ 06 мая 2020

Вот способ добиться желаемого:

numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4]

result = []
def split_list(list_):
    first = list_.pop(0)
    result.append(list_[:first])
    if len(list_[first:]) > 0:
        split_list(list_[first:])

split_list(numbers)

print(result)
0 голосов
/ 06 мая 2020

Я отредактировал свой ответ, вдохновленный кем-то еще в этой теме. Это не использует исходный массив и использует рекурсию вместо цикла.

numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4, 3,1,1,1,1]

def do_take(numbers: []):
    result = []
    to_take = numbers[0]
    result.append(numbers[1:to_take + 1])
    if len(numbers) > to_take:
        result.append(do_take(numbers[to_take + 1:]))
    return result

print(do_take(numbers))
print(numbers)

Результат будет следующим:

# python /tmp/breakup.py
[[1, 2, 3], [[1, 2, 3, 4], [[1, 1, 1], [[]]]]]
[3, 1, 2, 3, 4, 1, 2, 3, 4, 3, 1, 1, 1, 1]
...