2016-05-10 1 views
1

У меня есть вопрос относительно общих данных. У меня есть три текстовые файлы, которые содержат данные в следующем формате:Вывод соответствующих строк из трех текстовых файлов, а также строки под соответствующей строкой

cli= 111 
    mon= 45 

    cli= 584 
    mon= 21 

    cli= 23 
    mon= 417 

Теперь у меня есть следующая программа whcih когда я исполню его, он дает мне все CLI соответствия. Другими словами, это дает мне CLI, который появился в трех текстовых файлах.

with open ('/home/user/Desktop/text1.txt', 'r') as file1: 
    with open ('/home/user/Desktop/text2.txt', 'r') as file2: 
      with open ('/home/user/Desktop/text3.txt', 'r') as file3: 
        same = set(file1).intersection(file2).intersection(file3) 
same.discard('\n') 

with open ('/home/user/Desktop/common.txt', 'w') as file_out: 
    for line in same: 
      file_out.write(line) 

Мой вопрос: могу ли я также вывести значение (MON = 45) вместе с CLI = 111? Предположим, что CLI = 111 присутствует во ВСЕХ из трех текстовых файлов. Я хочу получить что-то вроде этого:

cli= 111 
    mon= 45 
    mon= 98 
    mon= 32 

Заранее спасибо. PS: приведенные выше данные образца имеют всего 1 текстовый файл. Предположим, что есть 3 текстовых файла. Благодаря!

+0

Итак, вы хотите, чтобы соответствующий mon после каждого cli отображался во всех файлах? –

+0

@ Подушечный Каннингем точно! – starshine

+0

О, хорошо, что легко сделать с диктоном, я что-то брошу вместе –

ответ

0

Похоже, что вы выбрасывая данные, которые вы хотите последующий доступ. Если вы не будете снова разбирать файлы, вам нужно как-то захватить эти данные, чтобы вы больше не просматривали файл. Способ сделать это (предполагая, что каждый «cli» имеет только один соответствующий «mon» для каждого файла) будет со словарем.

Я создал функцию, которая строит словарь из предоставленного файла, где ключи являются данными «cli», а значениями являются данные mon. Оттуда вы можете построить Set() из ключей словаря и найти пересечение таким образом. От пересечения, вы знаете, что возвращаемые значения должны быть ключами в словаре, поэтому просто сцепить их в «из» строки и написать, что ваш из файла :)

def buildDict(f): 
     dic = {} 
     for i in range(0,len(f)): 
      if "cli" in f[i]: 
       dic[f[i]] = f[i+1] 
     return dic 

    with open ('1.txt', 'r') as file1: 
     f1_dic = buildDict(file1.readlines()) 
     with open ('2.txt', 'r') as file2: 
      f2_dic = buildDict(file2.readlines()) 
      with open ('3.txt', 'r') as file3: 
       f3_dic = buildDict(file3.readlines()) 
       same = set(f1_dic.keys()).intersection(f2_dic.keys()).intersection(f3_dic.keys()) 

    out = '' 
    for i in same: 
     out += i 
     out += f1_dic[i] 
     out += f2_dic[i] 
     out += f3_dic[i] 


    with open ('common.txt', 'w') as file_out: 
     file_out.write(out) 
0

Вы можете сгруппировать данные в Словаре тянущие линию после Cli годов, которые во всех файлах:

with open('text1.txt', 'r') as file1, open('text2.txt', 'r') as file2, open('text3.txt', 'r') as file3: 
    inter = set(file1).intersection(file2).intersection(file3) 

    # create a dict using lists as values to group the mons and remove empty lines 
    d = {k: [] for k in inter if k.strip()} 
    # don't need set anymore, dict lookups are also O(1) 
    del inter 
    # reset pointers 
    file1.seek(0), file2.seek(0), file3.seek(0) 

    # iterate over files again 
    for f in [file1, file2, file3]: 
     for line in f: 
      if line in d: 
       # pull next line if we get a match. 
       d[line].append(next(f)) 

Тогда просто написать содержание Dict:

with open('/home/user/Desktop/common.txt', 'w') as file_out: 
    for k,v in d.items(): 
     file_out.write(k) 
     for line in v: 
      file_out.write(line) 

Если вы ищете конкретная строка, то есть начиная с cli =, тогда другой подход состоял в том, чтобы сначала построить файл dict с данными file1, а затем перебрать оставшуюся часть, когда вы идете писать только записи данных, где длина значения/списка равна == 3:

with open('text1.txt', 'r') as file1, open('text2.txt', 'r') as file2, open(
     'text3.txt', 'r') as file3: 
    # create dict from inital file storing following line after cli-.. inside list as value 
    d = {k: [next(file1)] for k in file1 if k.starstwith("cli=")} 

    for f in [file2, file3]: 
     for line in f: 
      if line in d: 
       d[line].append(next(f)) 

with open('/home/user/Desktop/common.txt', 'w') as file_out: 
    for k, v in d.items(): 
     # if len is three we have one from each 
     if len(v) == 3: 
      file_out.write(k) 
      for line in v: 
       file_out.write(line) 

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

0

Интересного хак вы туда попали для сборки наборов линий «на лету»; но, как вы видите, это просто слишком умно, так как линии mon отделены от линий cli. Так давайте попробуем чтение более тщательно, чтобы это не произошло:

import re 

def getfile(fname): 
    with open(fname) as file1: 
     text = file1.read() 
    records = text.split("\n\n") 
    return dict(re.search(r"cli= *(\d+)\nmon= *(\d+)", rec).groups() for rec in records) 

d1 = getfile('/home/user/Desktop/text1.txt') 
d2 = getfile('/home/user/Desktop/text2.txt') 
d3 = getfile('/home/user/Desktop/text3.txt') 
same = set(d1).intersection(d2).intersection(d3) 

print("cli="+same) 
print("mon="+d1[same]) 
print("mon="+d2[same]) 
print("mon="+d3[same]) 

Я повернул каждый файл в словарь, который отображает cli значения mon значений, так как они идут парами. Затем мы пересекаем значения cli и используем их для поиска значений mon.

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