【问题标题】:recursively split list into sub lists based on first element length根据第一个元素长度递归地将列表拆分为子列表
【发布时间】:2020-08-21 10:24:23
【问题描述】:

我正在为这个小问题而烦恼,我确信可以(并且应该)递归地解决这个问题。

# 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]]

我正在处理的列表总是遵循这个逻辑,第一个元素总是后面 n 个元素的长度。

编辑:

根据一些建议,我只是添加了一个 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]]

【问题讨论】:

  • 到目前为止你有什么尝试??你必须表现出某种努力
  • 这很容易出错。确定子列表长度的值必须完全正确。您所要求的仅适用于非常特定类型的列表。

标签: python list recursion multidimensional-array split


【解决方案1】:

简单的切片就可以了:

>>> 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]]

【讨论】:

  • 我们可以使用while a 来代替while len(a)。不要将两者中的哪一个视为pythonic。所以我评论了。 ;) 非常酷的答案顺便说一句。
  • 我认为消耗a 可能会有问题。我编辑了@GiftZwergrapper 的答案,以将所有内容都保留在函数范围内并更具可读性。他的实现可能是最有用的。
  • @MiesvanderLippe Gift 的回答使用了pop 方法,该方法在调用split_list 后改变了列表,numbers 将是[1, 2, 3, 4, 1, 2, 3, 4],他在list_ 的切片上调用递归调用所以numbers 不会再丢失任何元素。我在没有消耗或更改原始列表的情况下发布了答案,感谢您提供任何反馈。
  • 我需要检查一下我的眼睛 ;) 我很想知道这一点。@Ch3steR 我已经编辑了自己的答案,也解决了这个问题。
【解决方案2】:

这是实现您想要的方法:

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)

【讨论】:

  • list.pop(k) 首先移除并返回 k 处的元素,然后将 k 之外的所有元素向上移动一个位置。对于任何合理大小的数据,这将非常缓慢。
【解决方案3】:

您可以在此处使用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]]

【讨论】:

  • 这个解决方案非常漂亮!我最终使用了这个!
【解决方案4】:

我已在此线程中其他人的启发下编辑了我的答案。这不会消耗原始数组并使用递归而不是循环。

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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 2015-12-13
    • 2018-12-22
    • 2021-08-20
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多