2017-01-12 5 views
1

У меня есть .txt, заполненный данными, которые я хочу фильтровать (около 5800 строк), поскольку некоторые строки встречаются как дубликаты с той лишь разницей, что временная метка ровно через 2 часа. Те строки, которые являются поздней версией дубликата (например, первая строка в приложенном примере), должны быть опущены. Все остальные строки должны быть оставлены и записаны в новый .txt-файл.Удаление дубликатов из файла .txt и создание нового .txt-файла

1_3_IMM 2016-07-19 16:11:56 00:00:40 2 Sensor Check # should go 
1_3_IMM 2016-07-19 14:12:40 00:00:33 2 Sensor Check # should stay 
1_3_IMM 2016-07-19 14:11:56 00:00:40 2 Sensor Check # should stay 
1_3_IMM 2016-07-19 16:12:40 00:00:33 2 Sensor Check # should go 
1_4_IMM 2016-07-19 17:23:25 00:00:20 2 Sensor Check # should stay 
1_4_IMM 2016-07-19 19:23:25 00:00:20 2 Sensor Check # should go 
1_4_IMM 2016-07-19 19:15:24 00:02:21 2 Sensor Check # should stay 
1_4_IMM 2016-07-19 19:25:13 00:02:13 2 Sensor Check # should stay 

Я написал код в Python, выход представляет собой файл .txt с только 1 строка текста:

deleted 

Я не могу показаться, чтобы решить эту. Вы можете помочь? См. Код ниже.

import os 

def filter_file(): 
    with open("output.txt", "w") as output: 
     #open the input file from a specified directory 
     directory = os.path.normpath("C:/Users/sande_000/Documents/Python files") 
     for subdir, dirs, files in os.walk(directory): 
      for file in files: 
       if file.startswith("input"): 
        input_file=open(os.path.join(subdir, file)) 
        #iterate over each line of the file 
        for line in input_file: 
         machine = line[0:7]    #stores machine number 
         date = line[8:18]    #stores date stamp 
         time_1 = int(line[19:21])  #stores hour stamp 
         time_2 = int(line[22:24])  #stores minutes stamp 
         time_3 = int(line[25:27])  #stores second stamp 
         #check current line with other lines for duplicates by iterating over each line of the file 
         for otherline in input_file: 
          compare_machine = otherline[0:7]    
          compare_date = otherline[8:18] 
          compare_time_1 = int(otherline[19:21])+2 
          compare_time_2 = int(otherline[22:24]) 
          compare_time_3 = int(otherline[25:27]) 
          #check whether machine number & date/hour+2/minutes/seconds stamp are similar. 
          #If yes, write 'deleted' to output.txt and stop comparing lines. 
          #If no, continue with comparing next line. 
          if compare_machine == machine and compare_date == date and compare_time_1 == time_1 and compare_time_2 == time_2 and compare_time_3 == time_3: 
           output.write("deleted"+"\n") 
           break 
          else: 
           continue 
          #If no overlap between one line with any other line from the file, write that line to output.txt since it is no duplicate. 
          output.write(line) 

        input_file.close() 

if __name__ == "__main__": 
    filter_file() 
+0

Конечно '14: 12: 40' должен остаться и' 16: 12: 40' должен идти, не так ли? У вас все наоборот. – Tagc

+0

В вашем текстовом файле нет логики. Как только предыдущий должен пойти, а для другого - раньше. Кроме того, ваш файл журнала не сортируется по дате. Означает ли порядок? –

+0

Это действительно было ошибкой, текстовый файл должен быть логичным. Для всей ясности: раньше нужно было оставаться, а потом идти. Это правда, что файл журнала не сортируется по дате, я ничего не могу с этим поделать. – Sander

ответ

1

Я считаю, что код ниже работает. Обратите внимание, что этот код не будет работать, если есть какие-либо изменения в наименьших трех временных компонентах записей (миллисекунды, микросекунды, наносекунды) из-за того, что datetime не поддерживает разрешение за микросекундами. В вашем примере это не изменит ситуацию.

import os 
from datetime import datetime, timedelta 

INPUT_DIR = 'C:\Temp' 
OUTPUT_FILE = 'output.txt' 


def parse_data(data): 
    for line in data.splitlines(): 
     date_s = ' '.join(line.split()[1:3]) 
     date = datetime.strptime(date_s, '%Y-%m-%d %H:%M:%S') 
     yield line, date 


def filter_duplicates(data): 
    duplicate_offset = timedelta(hours=2) 

    parsed_data = list(parse_data(data)) 
    lines, dates = zip(*parsed_data) 

    for line, date in parsed_data: 
     if (date - duplicate_offset) not in dates: 
      yield line 


def get_input_data_from_dir(directory): 
    data = '' 
    for sub_dir, _, files in os.walk(directory): 
     for file in files: 
      if file.startswith('input'): 
       with open(os.path.join(sub_dir, file)) as f: 
        data += f.read() + '\n' 

    return data 


if __name__ == '__main__': 
    data = get_input_data_from_dir(INPUT_DIR) 
    with open(OUTPUT_FILE, 'w') as f_out: 
     content = '\n'.join(filter_duplicates(data)) 
     f_out.write(content) 

Испытаны на входной каталог со структурой:

[email protected] /cygdrive/c/Temp 
$ tree 
. 
├── input_1.txt 
└── input_2.txt 

input_1.txt:

1_3_IMM 2016-07-19 16:11:56 00:00:40 2 Sensor Check 
1_3_IMM 2016-07-19 14:12:40 00:00:33 2 Sensor Check 
1_3_IMM 2016-07-19 14:11:56 00:00:40 2 Sensor Check 
1_3_IMM 2016-07-19 16:12:40 00:00:33 2 Sensor Check 

input_2.txt:

1_4_IMM 2016-07-19 17:23:25 00:00:20 2 Sensor Check 
1_4_IMM 2016-07-19 19:23:25 00:00:20 2 Sensor Check 
1_4_IMM 2016-07-19 19:15:24 00:02:21 2 Sensor Check 
1_4_IMM 2016-07-19 19:25:13 00:02:13 2 Sensor Check 

output.txt в выполнение осле:

1_3_IMM 2016-07-19 14:12:40 00:00:33 2 Sensor Check 
1_3_IMM 2016-07-19 14:11:56 00:00:40 2 Sensor Check 
1_4_IMM 2016-07-19 17:23:25 00:00:20 2 Sensor Check 
1_4_IMM 2016-07-19 19:15:24 00:02:21 2 Sensor Check 
1_4_IMM 2016-07-19 19:25:13 00:02:13 2 Sensor Check 

Ваш ожидаемый результат ниже, скопирована для удобства:

1_3_IMM 2016-07-19 16:11:56 00:00:40 2 Sensor Check # should go 
1_3_IMM 2016-07-19 14:12:40 00:00:33 2 Sensor Check # should stay 
1_3_IMM 2016-07-19 14:11:56 00:00:40 2 Sensor Check # should stay 
1_3_IMM 2016-07-19 16:12:40 00:00:33 2 Sensor Check # should go 
1_4_IMM 2016-07-19 17:23:25 00:00:20 2 Sensor Check # should stay 
1_4_IMM 2016-07-19 19:23:25 00:00:20 2 Sensor Check # should go 
1_4_IMM 2016-07-19 19:15:24 00:02:21 2 Sensor Check # should stay 
1_4_IMM 2016-07-19 19:25:13 00:02:13 2 Sensor Check # should stay 
+0

Я писал почти такой же код на Python и был на 80%, когда видел ваше сообщение. Upvoted.Одна проблема: автор попросил написать «delete» при просмотре дубликата – hansaplast

+0

@hansaplast »автор попросил написать« удалить »при просмотре дубликата« Где вы это видели? OP написал * «Те строки, которые являются последней версией дубликата (например, первая строка в приложенном примере), должны быть опущены». * – Tagc

+0

@hansaplast О, я вижу, я посмотрел на вопрос, но не на комментарии в его коде. Я попытаюсь обновить свой ответ. – Tagc

0

Я думаю, что этот более короткий код должен это сделать. Имеет два последовательных цикла вместо вложенных циклов, которые должны повысить производительность.

from datetime import datetime, timedelta 

# os.walk etc. 

for file in files: 
    if not file.startswith("input"): 
     continue 

    entries = set() 

    # build up entries 
    for line in input_file: 
     machine = line[0:7]    #stores machine number 
     date = datetime.strptime(line[8:27], '%Y-%m-%d %H:%M:%S') 

     entries.add((machine, date)) 

    #check entries 
    for line in input_file: 
     machine = line[0:7]    #stores machine number 
     date = datetime.strptime(line[8:27], '%Y-%m-%d %H:%M:%S') - timedelta(hours=2) 

     if (machine, date) in entries: 
      output.write("deleted\n") 
     else: 
      output.write(line) 
     output.flush() 
+0

Пробовал это несколько раз и выглядит чистым для меня, но он ничего не пишет в output.txt. Просто пустой файл ... – Sander

+0

Возможно, вам придется вызвать output.flush() после записи. –

+0

К сожалению, никакого эффекта – Sander

Смежные вопросы