How to interleave two lists by chunks
Question:
I want to combine two lists but in a specific way. I want every 4 values to change the list I am taking values from.
Here is an example, but the dataset I am working on is much bigger:
List1 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8]
List2 = [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8]
#Expected merged list
[1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 1.5, 1.6, 1.7, 1.8, 2.5, 2.6, 2.7, 2.8]
Here I’m taking the first 4 from List1
, then taking the next 4 from List2
, and then go back to List1
etc.
This is similar to the Intertwining two lists question but instead of having:
c = [a[0], b[0], a[1], b[1], ..., a[n], b[n]]
I want
c = [a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3], ..., a[n-3], a[n-2], a[n-1], a[n], b[n-3], b[n-2], b[n-1], b[n]]
Answers:
What about this:
A = [1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3]
B = [2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2, 2.3, 2.3]
sep = 4
num = len(A)
iterations = int(num / sep) + 1
merged = []
for i in range(iterations):
start = sep * i
end = sep * (i + 1)
merged.extend(A[start:end])
merged.extend(B[start:end])
print(merged)
>>> '[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 1.3, 1.3, 2.3, 2.3]'
You can try this. You can use extend
.
>>> l=[]
>>> for i in range(0,len(List1),4):
l.extend(List1[i:i+4])
l.extend(List2[i:i+4])
>>> l
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2]
>>>
This code should work just about well:
lst1 = [1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2]
lst2 = [2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2]
def combine(lst1 = [], lst2 = []):
result = []
for i in range(0,len(lst1), 4):
for j in range(i, i + 4):
result.append(lst1[i])
result.append(lst2.pop(0))
result.append(lst2.pop(0))
for item in lst2:
result.append(item)
return result
print(combine(lst1, lst2)) # [1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2]
We step through the first list four times, then add all the items into our result and removing the first 2 head elements into lst2 into our result, then finally whatever is left in lst2 is also loaded into our result.
You could simply try this:
l=[List1[0]]*4+[List2[1]]*4+[List1[-1]]*4+[List2[-1]]*4
In case you want to be able to handle any list lengths (not just divisible by 4, and not just where the two lists have the same size) and any number of lists…
Any list lengths
This can handle any list lengths, including where the two lists have wildly different lengths:
result = []
it1, it2 = iter(List1), iter(List2)
while chunk := list(islice(it1, 4)) + list(islice(it2, 4)):
result += chunk
Slight alternative:
result = []
it1, it2 = iter(List1), iter(List2)
while chunk := list(chain(islice(it1, 4), islice(it2, 4))):
result += chunk
Demo:
>>> from itertools import islice
>>> List1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> List2 = ['a', 'b', 'c', 'd', 'e']
>>> k = 4
>>> result = []
>>> it1, it2 = iter(List1), iter(List2)
>>> while chunk := list(islice(it1, k)) + list(islice(it2, k)):
result += chunk
>>> result
[1, 2, 3, 4, 'a', 'b', 'c', 'd', 5, 6, 7, 8, 'e', 9, 10, 11, 12, 13, 14]
Any number of lists (of any lengths)
result = []
iters = deque(map(iter, Lists))
while iters:
it = iters.popleft()
if chunk := list(islice(it, 4)):
result += chunk
iters.append(it)
Demo (output formatted for clarity):
>>> from itertools import islice
>>> from collections import deque
>>> Lists = [
[1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2],
[2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2, 2.3],
[3.1, 3.1, 3.1, 3.1, 3.2, 3.2, 3.2, 3.2, 3.3, 3.4]
]
>>> k = 4
>>> result = []
>>> iters = deque(map(iter, Lists))
>>> while iters:
it = iters.popleft()
if chunk := list(islice(it, 4)):
result += chunk
iters.append(it)
>>> result
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 3.1, 3.1, 3.1, 3.1,
1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 3.2, 3.2, 3.2, 3.2,
2.3, 3.3, 3.4]
As my other answer, this can handle any list lengths, but this can also handle any number of lists:
def gen(i, lst):
for j, x in enumerate(lst):
yield j // 4, i, x
result = [x[2] for x in merge(*(gen(*e) for e in enumerate(Lists)))]
Demo:
>>> from heapq import merge
>>> Lists = [
[1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2],
[2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2],
[3.1, 3.1, 3.1, 3.1, 3.2, 3.2, 3.2, 3.2]
]
>>> def gen(i, lst):
for j, x in enumerate(lst):
yield j // 4, i, x
>>> [x[2] for x in merge(*(gen(*e) for e in enumerate(Lists)))]
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 3.1, 3.1, 3.1, 3.1,
1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 3.2, 3.2, 3.2, 3.2]
I want to combine two lists but in a specific way. I want every 4 values to change the list I am taking values from.
Here is an example, but the dataset I am working on is much bigger:
List1 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8]
List2 = [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8]
#Expected merged list
[1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 1.5, 1.6, 1.7, 1.8, 2.5, 2.6, 2.7, 2.8]
Here I’m taking the first 4 from List1
, then taking the next 4 from List2
, and then go back to List1
etc.
This is similar to the Intertwining two lists question but instead of having:
c = [a[0], b[0], a[1], b[1], ..., a[n], b[n]]
I want
c = [a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3], ..., a[n-3], a[n-2], a[n-1], a[n], b[n-3], b[n-2], b[n-1], b[n]]
What about this:
A = [1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2, 1.3, 1.3]
B = [2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2, 2.3, 2.3]
sep = 4
num = len(A)
iterations = int(num / sep) + 1
merged = []
for i in range(iterations):
start = sep * i
end = sep * (i + 1)
merged.extend(A[start:end])
merged.extend(B[start:end])
print(merged)
>>> '[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 1.3, 1.3, 2.3, 2.3]'
You can try this. You can use extend
.
>>> l=[]
>>> for i in range(0,len(List1),4):
l.extend(List1[i:i+4])
l.extend(List2[i:i+4])
>>> l
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2]
>>>
This code should work just about well:
lst1 = [1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2]
lst2 = [2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2]
def combine(lst1 = [], lst2 = []):
result = []
for i in range(0,len(lst1), 4):
for j in range(i, i + 4):
result.append(lst1[i])
result.append(lst2.pop(0))
result.append(lst2.pop(0))
for item in lst2:
result.append(item)
return result
print(combine(lst1, lst2)) # [1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 1.2, 1.2, 1.2, 1.2, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2]
We step through the first list four times, then add all the items into our result and removing the first 2 head elements into lst2 into our result, then finally whatever is left in lst2 is also loaded into our result.
You could simply try this:
l=[List1[0]]*4+[List2[1]]*4+[List1[-1]]*4+[List2[-1]]*4
In case you want to be able to handle any list lengths (not just divisible by 4, and not just where the two lists have the same size) and any number of lists…
Any list lengths
This can handle any list lengths, including where the two lists have wildly different lengths:
result = []
it1, it2 = iter(List1), iter(List2)
while chunk := list(islice(it1, 4)) + list(islice(it2, 4)):
result += chunk
Slight alternative:
result = []
it1, it2 = iter(List1), iter(List2)
while chunk := list(chain(islice(it1, 4), islice(it2, 4))):
result += chunk
Demo:
>>> from itertools import islice
>>> List1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> List2 = ['a', 'b', 'c', 'd', 'e']
>>> k = 4
>>> result = []
>>> it1, it2 = iter(List1), iter(List2)
>>> while chunk := list(islice(it1, k)) + list(islice(it2, k)):
result += chunk
>>> result
[1, 2, 3, 4, 'a', 'b', 'c', 'd', 5, 6, 7, 8, 'e', 9, 10, 11, 12, 13, 14]
Any number of lists (of any lengths)
result = []
iters = deque(map(iter, Lists))
while iters:
it = iters.popleft()
if chunk := list(islice(it, 4)):
result += chunk
iters.append(it)
Demo (output formatted for clarity):
>>> from itertools import islice
>>> from collections import deque
>>> Lists = [
[1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2],
[2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2, 2.3],
[3.1, 3.1, 3.1, 3.1, 3.2, 3.2, 3.2, 3.2, 3.3, 3.4]
]
>>> k = 4
>>> result = []
>>> iters = deque(map(iter, Lists))
>>> while iters:
it = iters.popleft()
if chunk := list(islice(it, 4)):
result += chunk
iters.append(it)
>>> result
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 3.1, 3.1, 3.1, 3.1,
1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 3.2, 3.2, 3.2, 3.2,
2.3, 3.3, 3.4]
As my other answer, this can handle any list lengths, but this can also handle any number of lists:
def gen(i, lst):
for j, x in enumerate(lst):
yield j // 4, i, x
result = [x[2] for x in merge(*(gen(*e) for e in enumerate(Lists)))]
Demo:
>>> from heapq import merge
>>> Lists = [
[1.1, 1.1, 1.1, 1.1, 1.2, 1.2, 1.2, 1.2],
[2.1, 2.1, 2.1, 2.1, 2.2, 2.2, 2.2, 2.2],
[3.1, 3.1, 3.1, 3.1, 3.2, 3.2, 3.2, 3.2]
]
>>> def gen(i, lst):
for j, x in enumerate(lst):
yield j // 4, i, x
>>> [x[2] for x in merge(*(gen(*e) for e in enumerate(Lists)))]
[1.1, 1.1, 1.1, 1.1, 2.1, 2.1, 2.1, 2.1, 3.1, 3.1, 3.1, 3.1,
1.2, 1.2, 1.2, 1.2, 2.2, 2.2, 2.2, 2.2, 3.2, 3.2, 3.2, 3.2]