Мне нужно читать огромные файлы, структурированные как многострочные записи, и записывать в файл записи с определенными индексами, скажем, номера записей R = 1, 2 и 1093. Если каждая запись состоит из N = 3 строк, это равносильно чтению файла построчно, а затем записи строк с номерами 1, 2, 3 и 4, 5, 6 и 3277, 3278, 3279 (в том смысле, что первая строка в каждой записи Ri начинается по номеру строки Ri-1*N+1.
Я предполагаю, что можно рассчитать строки для записи и просмотреть файл строка за строкой и записать эти строки. Однако возможно ли «заархивировать» последовательные строки 1, 2 и 3 в объект генератора, содержащий записи, и каким-то образом отфильтровать их или распечатать их непосредственно в файл, если они перечисляются в R ? Что-то в этом псевдокоде:
def subset(file_in, file_out, N, R):
with open(file_in, "rt") as fin, open(file_out, "wt") as fout:
line = (line.rstrip() for line in fin)
record = enumerate(zip(line, line, line)) # What if records are of size N
for i, r in record if i in R:
fout.write(r)
Что делать, если вы хотите, чтобы размер записи N был параметром?
ПРИМЕР ОБНОВЛЕНИЯ
Пример для file_in (4 записи, 3 строки/запись):
dslfkj
2
a
dflkj
3
g
fds
2
b
fsdlkj
1
n
Тогда подмножество (file_in, file_out, 3, [1,3]) даст (file_out)
dslfkj
2
a
fds
2
b
Нет, тогда мне нужно будет рассчитать строки для печати (как упоминалось во вступлении к моему вопросу), верно?
ммм, это определенно самое чистое.
Возможный дубликат Итерировать N элементов за раз на генераторе с одним выходом
@Suparshva Я думаю, что конкретные записи не выбираются (но я мог неправильно прочитать этот пост.
@ user3375672 из вашего кода вы, кажется, получаете n строк за раз (которые вы считаете записью ... первые n строк записывают 1, следующие n строк записывают 2 и так далее) ... теперь вам нужны конкретные записи, скажем, 1, 3 7 (поправьте меня, если я неправильно понял) ... поэтому, как только у вас есть генератор, как в ответе, вы можете иметь другой генератор, который дает эти записи 1,3 и 7 (возьмите его как входной список) ... номер записи, который вы можете отслеживать, сколько раз вы выполняли выход на первый генератор ... ваш вопрос задавался "Что делать, если вы хотите, чтобы размер записи N был параметром?"
Для этой задачи имеет смысл просто решить ее непосредственно построчно, используя деление по этажам.
Например:
fin = '''
dslfkj
2
a
dflkj
3
g
fds
2
b
fsdlkj
1
'''
line_gen = (line.rstrip() for line in fin.strip().split())
R = [1, 3]
R = [val - 1 for val in R] #zero indexing
N = 3
for i, line in enumerate(line_gen):
if i // N in R:
print(line)
Выход:
dslfkj
2
a
fds
2
b
Ваша функция может выглядеть примерно так: (вы можете проверить, работает ли она «из коробки» или требует настроек. Я не проверял часть открытия файла.
def subset(file_in, file_out, N, R):
R = [val - 1 for val in R] #zero indexing
with open(file_in, "rt") as fin, open(file_out, "wt") as fout:
line_gen = (line.rstrip() for line in fin)
for i, line in enumerate(line_gen):
if i // N in R:
fout.write(line)
fout.write('\n')
Обновлено: ответ ниже относится к тому, как вы можете использовать генераторы и группировать значения вместе. Сказав это, я не думаю, что вам нужно его использовать. Однако, если вы все еще хотите, вы можете построить свою функцию на ее основе.
Старый ответ:
Вы можете создать n
ссылки на объект с помощью списка, а затем распаковать с помощью файла *
(также известный как знак) оператор.
Например:
from itertools import zip_longest
line = (x for x in range(100, 132))
n = 3
record = zip(*([line] * n)) #equivalent to *[line, line, line] which is unpacked into zip arguments
for i, r in enumerate(record):
print(i, r)
0 (100, 101, 102)
1 (103, 104, 105)
2 (106, 107, 108)
3 (109, 110, 111)
4 (112, 113, 114)
5 (115, 116, 117)
6 (118, 119, 120)
7 (121, 122, 123)
8 (124, 125, 126)
9 (127, 128, 129)
Кроме того, в зависимости от того, что вы хотите сделать для «остаточных» строк, вы можете вместо этого использовать zip_длиннейший.
Точно - возможно, вашей функции нужна новая строка в write()
Чуть аккуратнее, пожалуй, с одной строкой print(line, file = fout)
XY проблема. вам не нужно группировать или собирать эти строки, чтобы иметь возможность получить этот вывод.