2013-06-03 2 views
1

У меня есть два файла, которые выглядят, как это с некоторыми различиями между ними:получать минимальные значения элементов с одинаковым идентификатором, если разница существует?

Первый файл:

{16:[3, [-7, 87, 20, 32]]} 
{17:[2, [-3, 88, 16, 28], 3, [-6, 84, 20, 32]]} 
{18:[2, [-1, 88, 16, 28], 3, [-3, 84, 20, 32]]} 
{19:[2, [1, 89, 16, 28], 3, [-2, 85, 20, 32]]} 
{20:[2, [9, 94, 16, 28], 3, [1, 85, 20, 32]]} 
{21:[2, [12, 96, 16, 28], 3, [2, 76, 19, 31]]} 
{22:[2, [15, 97, 16, 28], 3, [4, 73, 19, 29]]} 
{23:[2, [18, 96, 16, 28], 3, [6, 71, 19, 29], 10, [-10, 60, 51, 82]]} 
{24:[2, [22, 97, 16, 28], 3, [9, 71, 19, 27], 10, [-5, 63, 49, 78]]} 
{25:[2, [25, 99, 16, 28], 3, [13, 71, 17, 26], 10, [-1, 64, 46, 77]]} 
{26:[2, [29, 101, 16, 28], 3, [17, 70, 16, 25], 10, [-1, 65, 45, 77]]} 

Второй файл:

{16:[3, [-7, 86, 20, 32]]} 
{17:[2, [-3, 82, 16, 28], 3, [-6, 84, 20, 32]]} 
{18:[2, [-1, 88, 16, 27], 3, [-3, 84, 20, 32]]} 
{19:[2, [1, 89, 16, 28], 3, [-2, 84, 20, 32]]} 
{20:[2, [9, 94, 15, 28], 3, [1, 85, 20, 32]]} 
{21:[2, [12, 96, 16, 28], 3, [1, 76, 19, 31]]} 
{22:[2, [15, 97, 17, 28], 3, [4, 73, 19, 29]]} 
{23:[2, [18, 96, 18, 28], 3, [6, 71, 19, 29], 10, [-10, 60, 51, 82]]} 
{24:[2, [22, 97, 16, 28], 3, [9, 71, 20, 27], 10, [-5, 63, 49, 78]]} 
{25:[2, [25, 99, 16, 28], 3, [13, 71, 17, 26], 10, [-1, 64, 46, 77]]} 
{26:[2, [29, 101, 17, 28], 3, [17, 70, 16, 25], 10, [-1, 65, 45, 77]]} 

Я сравниваю их обоих, используя difflib и распечатывать линии, которые имеют в них разницу. То, что я пытаюсь сделать, это распечатать минимальные и максимальные значения frame, которые разделяют одинаковые id.

Рамка является ключом в каждой строке, поэтому в этом случае рамки в диапазоне от 16 до 26. Идентификатор - это значение, которое предшествует каждому списку из 4 значений. Таким образом, идентификатор на первой строке - 3. Вторая строка имеет два идентификатора: 2, а затем 3.

Так пример того, что я хотел бы, чтобы написать это:

17 - 36 

при условии, что один из frames, разделяющего идентификатора 3 отличается от файла, который я сравниваю с.

Для каждого отличия мне нужно записать новый файл, содержащий только начальный кадр и конечный кадр, тогда я буду работать над объединением дополнительных строк в каждый файл.

это текущее использование difflib, который печатает каждую строку, которая имеет разные:

def compare(f1, f2): 
    with open(f1+'.txt', 'r') as fin1, open(f2+'.txt', 'r') as fin2: 
     diff = difflib.ndiff(fin1.readlines(), fin2.readlines()) 
     outcome = ''.join(x[2:] for x in diff if x.startswith('- ')) 
     print outcome 

Как бы я быть в состоянии добиться того, что я описал выше настройки этого исполнения блока?

Обратите внимание, что оба файла имеют один и тот же номер frame, но не тот же id s, поэтому мне нужно было написать два разных файла для каждой разницы, возможно, в папку. Поэтому, если два файла имеют 20 отличий, мне нужно иметь две основные папки по одному для каждого исходного файла, каждый из которых содержит текстовые файлы для каждого начала и конца frame того же идентификатора.

ответ

1

Предположим, ваш список различий - это содержимое файла, которое вы даете в начале своего сообщения. Я исходил в 2 раза, 1-й список ПОЛУЧИТЬ кадров в ID:

>>> from collections import defaultdict 
>>> diffs = defaultdict(list) 
>>> for line in s.split('\n'): 
    d = eval(line) # We have a dict 
    for k in d: # Only one value, k is the frame 
     # Only get even values for ids 
     for i in range(0, len(d[k]), 2): 
      diffs[d[k][i]].append(k) 


>>> diffs # We now have a dict with ids as keys : 
defaultdict(<type 'list'>, {10: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36], 2: [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], 3: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36], 29: [31, 32, 33, 34, 35, 36]}) 

Теперь мы получаем диапазоны каждый идентификатор, благодаря this other SO post, что помогает получать диапазоны из списка индексов:

>>> from operator import itemgetter 
>>> from itertools import groupby 
>>> for id_ in diffs: 
    diffs[id_].sort() 
    for k, g in groupby(enumerate(diffs[id_]), lambda (i, x): i - x): 
     group = map(itemgetter(1), g) 
     print 'id {0} : {1} -> {2}'.format(id_, group[0], group[-1]) 


id 10 : 23 -> 36 
id 2 : 17 -> 33 
id 3 : 16 -> 36 
id 29 : 31 -> 36 

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

EDIT: вот окончательный ответ с такой же блок:

>>> def compare(f1, f2): 
    # 2 embedded 'with' because I'm on Python 2.5 :-) 
    with open(f1+'.txt', 'r') as fin1: 
     with open(f2+'.txt', 'r') as fin2: 
      lines1 = fin1.readlines() 
      lines2 = fin2.readlines() 
        # Do not forget the strip function to remove unnecessary '\n' 
      diff_lines = [l.strip() for l in lines1 if l not in lines2] 
        # Ok, we have our differences (very basic) 
      diffs = defaultdict(list) 
      for line in diff_lines: 
       d = eval(line) # We have a dict 
       for k in d: 
        list_ids = d[k] # Only one value, k is the frame 
        for i in range(0, len(d[k]), 2): 
         diffs[d[k][i]].append(k) 
      for id_ in diffs: 
       diffs[id_].sort() 
       for k, g in groupby(enumerate(diffs[id_]), lambda (i, x): i - x): 
        group = map(itemgetter(1), g) 
        print 'id {0} : {1} -> {2}'.format(id_, group[0], group[-1]) 

>>> compare(r'E:\CFM\Dev\Python\test\f1', r'E:\CFM\Dev\Python\test\f2') 
id 2 : 17 -> 24 
id 2 : 26 -> 26 
id 3 : 16 -> 24 
id 3 : 26 -> 26 
id 10 : 23 -> 24 
id 10 : 26 -> 26 
+0

Это очень полезно, спасибо большое! Тем не менее, я не понимаю, что такое «s» в третьей строке »для строки в s.split ('\ n'): – MaxPower

+0

О, да, извините :-) 's' - это просто большая строка, содержащая все строки, которые вы показываете в начале, это означает список различий. – Emmanuel

+1

Мое редактирование показывает полное решение, надеюсь, что это то, что вам нужно ... – Emmanuel