I have two lists as follows.
l1=[a,b,c,d,e]
l2=[[p,q],[r,s,t]]
How do I create a list of lists from l1 similar to list l2 ?
Desired output: [[a,b],[c,d,e]]
Your help is much appreciated. Thanks!
CodePudding user response:
One possible approach: use deepcopy(l2)
to create the structure of the new list, and then recursively traverse it and replace its non-list items with items taken from a copy of 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']]
This should work with arbitrarily deep lists (up to Python's recursion limit anyway).
If preserving the original l1
and l2
isn't important, you can skip the copy
and deepcopy
calls.
CodePudding user response:
The following approach will work for arbitrarily nested lists, and doesn't require a deep copy nor an inefficient pop
from the end of the list, making this version linear on the total number of items, instead of quadratic:
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))
Also, just for fun, here's an iterative solution:
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]
Also, here's a breadth-first approach, which we can modify the iterative approach easily and use the standard queue-based approach:
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]
For the differences:
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']]
CodePudding user response:
You can create an empty list to store the result, and a count
variable to store the start index for each sub-list, then for each sublist in l2
, get the size of the sublist, and take the items from list l1
res = []
count = 0
for sub in l2:
res.append(l1[count:len(sub) count])
count = len(sub)
OUTPUT:
res
Out[79]: [['a', 'b'], ['c', 'd', 'e']]