2016-02-03 2 views
0

Я хочу разобрать файл csv с помощью python. Чтобы сделать это, я хочу создать копию того же файла, а затем проанализировать его по строкам.Сделайте копию файла и удалите строки, которые соответствуют условию?

Если одна из строк удовлетворяет условию, я хочу, чтобы эта строка была удалена из временного файла и помещена в новый файл.

Таким образом, я могу сделать tmp все меньше и меньше по мере его повторения по списку, поэтому есть меньше, чем синтаксический анализ, а также посмотреть, свободен ли временный файл в конце разбора и подтвердить, что мой синтаксический анализ работал отлично. Принимая во внимание, что я не повредил исходный файл.


Допустим, исходный файл содержит:

AAAAAAAAAA 
BBBBBBBBBB 
CCCCCCCCCC 
AAAAAAAAAA 
BBBBBBBBBB 

то у меня есть список

list = [AAAAAAAAA, BBBBBBBBBB,CCCCCCCCCC] 

и я могу сделать что-то в строках:

for x in list: 
    for line in tmpCsv: 
     if x in line: 
      #remove line from tmpCsv place it to file x.CSV 
+0

В чем конкретно возникают проблемы? (Я бы, вероятно, попытался прочитать строку за строкой из исходного файла и записать в один из двух других файлов, если условные пропускают.) – JETM

+0

Я не знаю, как создать временный файл, не затрагивая оригинальный, а затем использовать временный файл для дальнейшего разбора при его модификации –

ответ

2

Файловые системы не работают. Вы не можете эффективно удалить что-то из середины файла на диске. Чтобы имитировать это действие, операционная система сначала копирует каждый байт в файл после удаленной строки, чтобы скрыть «отверстие», и, наконец, файл, чтобы выбросить конечные байты. Каждое удаление линии, выполненное таким образом, имеет сложность O (n), где n - размер файла, и для удаления всех строк требуется O (n) - это медленно.

Если файлы достаточно малы, вы можете прочитать весь файл и сохранить его в памяти. Если они слишком велики для хранения в ОЗУ (гигабайт), читайте по частям и обрабатывайте каждый отдельно (если это возможно).

Не требуется удалять согласованные линии, чтобы делать то, что вы, по-видимому, хотите сделать. Вы можете просто подсчитать количество согласованных строк и распечатать ошибку, если число равно нулю.

Более эффективная реализация возможна, но это должно работать для начала:

for x in list: 
    numberOfLinesMatched = 0 
    for line in tmpCsv: 
     if x in line: 
      numberOfLinesMatched += 1 # possibly break here 
    if numberOfLinesMatched == 0: 
     ... # print an error, not found in the file 
+0

, но, удалив строки из файла tmp, я думал, что он становится все меньше и меньше, и есть меньше для синтаксического анализа, поскольку я перебираю элементы в списке. Очевидно, это не так, верно? –

+0

Прежде всего, любые операции на диске являются порядками величин медленнее операций в ОЗУ. Если файлы не огромны, нет необходимости работать с файлами дисков.Во-вторых, есть способы улучшить этот код, но это немного выходит за рамки вопроса. Удаление элементов из середины списка происходит медленно по той же причине, что и для файла. Использование более эффективной структуры данных - путь (словарь или 'collections.Counter'). – kfx

1

Предположительно проанализированные данные будут меньше, чем весь файл. Таким образом, вы правильно устанавливаете меньший набор во внешнем цикле. Но вы должны сделать это за один проход. Ниже я приведу пример потенциального решения.

Это считывает файл по строкам. Если строка соответствует условию, описанному в параграфе 2, то она помещается в один файл. Если он не отвечает условиям, он помещается в другой файл.

import os 
if os.path.exists("match.csv") or os.path.exists("nonmatch.csv"): 
    raise False, "I AM NOT OVERWRITING A FILE" 
originalCsv = open(csvFile,'r') 
matchFile = open("match.csv","w" 
nonmatchFile = open("nonmatch.csv","w" 
while 1: 
    line = originalCsv.read() 
    if line == '': break 
    if line == meetsCondition: 
     nonmatchFile.writelines(line) 
    else: 
     matchFile.writelines(line) 
matchFile.close() 
nonmatchFile.close() 
originalCsv.close() 
Смежные вопросы