Здравствуйте, стоит следующая задача:
Есть 2 txt файла (количество строк в каждом произвольно). Необходимо строки из одного списка вставить в другой через определённый интервал, например, через каждые n строк.
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))
В случае, если задать
while i + n <= len(list2):
list2 - файл откуда берём строки для подстановки, код работает как надо.
Однако, при
while i + n <= len(list1):
Получаю ошибку:
list1.insert(i * n, list2[i])
IndexError: list index out of range
Прошу подсказать как реализовать подстановку строк из list2 в случае, если строк в list2 меньше, чем в list1. То есть когда строки в list2 кончатся, подстановка строк должна опять начаться с 0 элемента 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
При этом важно, чтобы строки подставлялись именно из list2 в list1. И когда строки в list2 кончатся, они должны опять начать подставляться с 0 элемента.
Ответ
Чтобы элементы по кругу возвращались (начинались с первого по окончанию), можно itertools.cycle() использовать.
Чтобы по несколько элементов сразу обходить, можно zip(*[iterator]*n) идиому применить.
Чтобы чередовать группы из первого итератора с элементами из второго и вернуть плоскую версию (без рекурсии) и обрезая ввод по меньшей длине аргументов:
import itertools
flatten = itertools.chain.from_iterable
def interlaced(groups, items):
return flatten(itertools.chain(group, [item]) for group, item in zip(groups, items))
Объединяя :
n = 3
lines = interlaced(zip(*[itertools.cycle(f1)]*(n-1)), f2)
output_file.writelines(lines)
Пример:
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