将列表列表的结构复制到平面列表?

Copying structure of a list of list to a flat list?

我有两个列表如下。

l1=[a,b,c,d,e]
l2=[[p,q],[r,s,t]]

如何从 l1 创建类似于列表 l2 的列表列表?

期望的输出: [[a,b],[c,d,e]]

非常感谢您的帮助。谢谢!

您可以创建一个空列表来存储结果,并创建一个count变量来存储每个子列表的起始索引,然后对于l2中的每个子列表,获取大小子列表,并从列表 l1

中取出项目
res = []
count = 0
for sub in l2:
    res.append(l1[count:len(sub)+count])
    count += len(sub)
  

输出:

res
Out[79]: [['a', 'b'], ['c', 'd', 'e']]

一种可能的方法:使用deepcopy(l2)创建新列表的结构,然后递归遍历它并将其非列表项替换为从l1的副本中获取的项。

>>> a, b, c, d, e = "abcde"
>>> p, q, r, s, t = "pqrst"
>>> l1=[a,b,c,d,e]
>>> l2=[[p,q],[r,s,t]]
>>> from copy import deepcopy
>>> l3 = deepcopy(l2)
>>> def deep_replace(l1, l2):
...     for i, item in enumerate(l2):
...         if isinstance(item, list):
...             deep_replace(l1, item)
...         else:
...             l2[i] = l1.pop(0)
...
>>> deep_replace(l1.copy(), l3)
>>> l3
[['a', 'b'], ['c', 'd', 'e']]

这应该适用于任意深度的列表(无论如何达到 Python 的递归限制)。

如果保留原始 l1l2 并不重要,您可以跳过 copydeepcopy 调用。

以下方法适用于任意嵌套的列表,不需要深度复制,也不需要低效的 pop 从列表末尾开始,使这个版本与项目总数成线性关系,而不是二次方的:

def structured_replace(values, nested):
    it = iter(values)
    def _helper(nested):
        return [
            _helper(item) if isinstance(item, list) else next(it)
            for item in nested
        ]
    return _helper(nested)

a, b, c, d, e = "abcde"
p, q, r, s, t = "pqrst"
l1 = [a,b,c,d,e]
l2 = [[p,q],[r,s,t]]
print(structured_replace(l1, l2))

此外,为了好玩,这里有一个迭代解决方案:

def structured_replace(values, nested):
    it = iter(values)
    top_result = []
    stack = [(nested, top_result)]
    while stack:
        item, result = stack.pop()
        if isinstance(item, list):
            subresult = []
            result.append(subresult)
            for sub in reversed(item):
                stack.append((sub, subresult))
        else:
            result.append(next(it))
    return top_result[0]

此外,这里有一个广度优先方法,我们可以轻松修改迭代方法并使用标准的基于队列的方法:

def structured_replace_breadth_first(values, nested):
    from collections import deque
    it = iter(values)
    top_result = []
    stack = deque([(nested, top_result)])
    while stack:
        item, result = stack.popleft()
        if isinstance(item, list):
            subresult = []
            result.append(subresult)
            for sub in item:
                stack.append((sub, subresult))
        else:
            result.append(next(it))
    return top_result[0]

差异:

In [5]: structured_replace('abcdefg', [[1, 2], 3, [4, [5, 6], 7]])
Out[5]: [['a', 'b'], 'c', ['d', ['e', 'f'], 'g']]

In [6]: structured_replace_level_first('abcdefg', [[1, 2], 3, [4, [5, 6], 7]])
Out[6]: [['b', 'c'], 'a', ['d', ['f', 'g'], 'e']]