#python #csv
#python #csv
Вопрос:
Я хочу читать строки с последней по первую. Но я не могу этого сделать. Я хочу читать в обратном порядке.
stary_patient_2 ='Xs'
nowy_patient_2 = 'VB'
import csv
with open(DATA_DIR '/stage_2_train_labels_right.csv', 'r') as inp, open(DATA_DIR '/stage_2_train_labels_right_poprawne.csv', 'w') as out:
reader = csv.DictReader(inp, delimiter=' ',fieldnames = ['patientId','x', 'y', 'width', 'height', 'Target'])
writer = csv.DictWriter(out, fieldnames=reader.fieldnames)
writer.writeheader()
for row in reversed(list(open(DATA_DIR '/stage_2_train_labels_right.csv'))):
nowy_patient_2 = row[0]
print(row)
print(row[5])
if not (row[5]=='0' and nowy_patient_2==stary_patient_2):
writer.writerow({'patientId': row[0], 'x': row[1], 'y': row[2], 'width': row[3], 'height': row[4], 'Target': row[5]})
stary_patient_2 = nowy_patient_2
входной файл:
asdasd 1 2 3 4 5
dddddd 2 2 2 2 2
cccccc 3 2 5 6 1
вывод
cccccc 3 2 5 6 1
dddddd 2 2 2 2 2
asdasd 1 2 3 4 5
Ответ №1:
for row in reversed(list(open(DATA_DIR '/stage_2_train_labels_right.csv'))):
это не сработает, потому что вы снова открываете входной файл, а затем передаете не csv
объект, а дескриптор файла.
Просто преобразуйте reader
в list
, чтобы полностью прочитать файл, затем вы можете применить reversed
к списку строк.
with open(os.path.join(DATA_DIR,'stage_2_train_labels_right.csv'), newline="") as inp, open(os.path.join(DATA_DIR,'stage_2_train_labels_right_poprawne.csv'), 'w', newline="") as out:
reader = csv.DictReader(inp, delimiter=' ',fieldnames = ['patientId','x', 'y', 'width', 'height', 'Target'])
writer = csv.DictWriter(out, fieldnames=reader.fieldnames)
# read input file fully into a list of rows
reader = list(reader)
writer.writeheader()
# now iterate on reversed list
for row in reversed(reader):
Ответ №2:
Я не уверен, что это действительно возможно при чтении из файла. Файл считывается с помощью указателя файла, который указывает на начало файла. При перемещении указателя байт, на который вы смотрите, также изменяется — на самом деле у вас нет всего объекта в памяти, и поэтому вы не можете его отменить. Если вы действительно хотите, чтобы это было наоборот, вам, вероятно, нужно будет читать байт за байтом, постоянно возвращая один байт, а не строку за строкой. Итак, не зная точно, как будет сформирован файл, вот как может выглядеть read_last_line:
def read_last_line(path):
buffer = []
with open(path, 'r') as fh: # this might be easier not using with
fh.seek(0, os.SEEK_END) # read last byte
size = fh.tell()
r_pos = -1
while True:
fh.seek(size r_pos, 0)
ch = fh.read(1)
r_pos -= 1
if ch == 'n':
return list(reversed(buffer))
else:
buffer.append(ch)
Однако с этим есть проблемы: очевидно, что он получает только последнюю строку. Вам нужно будет адаптировать это для итерации по файлу. Во-вторых, он считывает файл на один байт за раз, что может быть проблемой. В-третьих, он возвращает список, когда вам может понадобиться что-то еще. и т.д. и т.п. Это не идеально.
Вот две альтернативы:
- Если у вас есть свободная память, вы можете просто прочитать весь файл целиком, разбить его на новые строки, а затем изменить это, чтобы получить тот же эффект, который вы хотите. Но если файлы слишком большие, то это будет проблемой.
- Если у вас есть контроль над файлом, вы можете либо записать его в обратном порядке, либо выполнить операцию чтения из файла и самостоятельно преобразовать его в новый файл. Это странно, поэтому менее идеально, но это может решить вашу проблему, если вы сможете записать другую версию этого файла на диск.
Комментарии:
1. У любого такого решения есть другая проблема с CSV, в частности: обычное определение строки не применяется к CSV. Вам необходимо учитывать кавычки / экранирование и определенный разделитель записей (например, простой
n
может не быть новой строкой, только сrn
подсчетом).2. Очень верно, и это применимо к любому формату, чьи «строки» не обязательно разделяются символом новой строки. Но вы столкнетесь с одной и той же проблемой, идущей вперед и назад. т. Е. в любом случае вам нужно будет адаптировать приведенный здесь код, чтобы он был полезен для вашей проблемной области.
3. Работа с пересылкой в порядке,
csv
модуль знает, как со всем этим справиться. Работая в обратном направлении,csv
модуль не может помочь, и вы застряли, переопределяя его с нуля, но в обратном направлении, что делает его еще более безумным.