【问题标题】:get min max values of items with same id if difference exists?如果存在差异,则获取具有相同 ID 的项目的最小最大值?
【发布时间】:2013-06-04 00:25:03
【问题描述】:

我有两个看起来像这样的文件,它们之间存在一些差异:

第一个文件:

 {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 比较它们并打印出它们之间存在差异的行。 我要做的是打印出共享相同id 的最小和最大frame 值。

帧是每一行的关键,因此在这种情况下,帧的范围从1626。 id 是每个 4 个值列表之前的值。所以第一行的id是3。第二行有两个 id,分别是 23

所以我想写的一个例子是:

17 - 36

鉴于共享 ID 3frames 之一与我要​​比较的文件不同。

对于每一个这样的差异,我需要写出一个只包含开始帧和结束帧的新文件,然后我将把额外的字符串连接到每个文件。

这是当前的 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 ammount 但不相同的 ids 所以我需要为每个差异写入两个不同的文件,可能写入一个文件夹。因此,如果这两个文件有 20 个不同之处,我需要为每个原始文件创建两个主文件夹,每个原始文件包含相同 ID 的每个开始和结束 frame 的文本文件。

【问题讨论】:

    标签: python difflib


    【解决方案1】:

    假设您的差异列表是您在帖子开头提供的文件内容。我进行了 2 次,第一次获取每个 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]})
    

    现在我们得到每个 id 的范围,感谢 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
    

    然后,对于每个 id,您都有差异范围。我想只要稍微调整一下,你就可以得到你想要的。

    编辑:这是相同类型的块的最终答案:

    >>> 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
    

    【讨论】:

    • 这很有帮助,非常感谢!但是,我不明白第三行中的“s”是什么“for line in s.split('\n'):
    • 哦,是的,抱歉 :-) s 只是包含您在开头显示的所有行的大字符串,它代表差异列表。
    • 唯一的事情是我需要它来打印出每个 id 的最小 - 最大帧数所以 id 2 : 17 -> 26 左右...但是再次感谢,我会处理的并尝试找出解决方案。
    • 哦,好吧,我以为你想要所有的范围!您只需将for id_ in diffs: 之后的所有复杂逻辑替换为:print min(diffs[id_]), max(diffs[id_]) 即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多