python-3.x – Insert elements of one list into another with a certain step

Question:

Hello, the task is as follows:

There are 2 txt files (the number of lines in each is arbitrary). It is necessary to insert lines from one list into another at a certain interval, for example, every n lines.

f1 = open(r'c:\Исходная база.txt')
f2 = open(r'c:\Строки для добавления.txt')
list1 = f1.readlines()
list2 = f2.readlines()
f1.close()
f2.close()
i = 0
n = 2
while i + n <= 10:
    list1.insert(i * n, list2[i])
    i = i + 1
with open(r'c:\результат.txt', 'w') as res:
    for item in list1:
        res.write("{}".format(item))

In case you ask

while i + n <= len(list2):

list2 – the file from where we take the lines for substitution, the code works as it should.

However, with

while i + n <= len(list1):

I get the error:

list1.insert(i * n, list2[i])

IndexError: list index out of range

I ask you to suggest how to implement the substitution of lines from list2 if there are fewer lines in list2 than in list1. That is, when the lines in list2 run out, line substitution must again start at 0 in list2.

Исходные данные list1: 1, 2, 3, 4, .., m
Исходные данные List2: a, b, c, d, .., k
Результат должен быть: 1, a, 2, b, 3, c ... при n=2
                       1, 2, a, 3, 4, b, .. при n=3

In this case, it is important that the lines are substituted exactly from list2 into list1. And when the lines in list2 run out, they should start substituting again from element 0.

Answer:

You can itertools.cycle() keep items in a circle (starting with the first one after the end).

To traverse multiple elements at once, you can apply the zip(*[iterator]*n) idiom.

To alternate groups from the first iterator with elements from the second and return a flat version (no recursion) and truncate the input to the shorter length of the arguments:

import itertools

flatten = itertools.chain.from_iterable

def interlaced(groups, items):
    return flatten(itertools.chain(group, [item]) for group, item in  zip(groups, items))

By combining:

n = 3
lines = interlaced(zip(*[itertools.cycle(f1)]*(n-1)), f2)
output_file.writelines(lines)

Example:

f1 = iter([1,2,3,4])
f2 = iter("abcde")
it = interlaced(zip(*[itertools.cycle(f1)]*(n-1)), f2)
print(*it)
# -> 1 2 a 3 4 b 1 2 c 3 4 d 1 2 e
Scroll to Top