python按层级找出xml文件的差异

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python按层级找出xml文件的差异相关的知识,希望对你有一定的参考价值。

使用Python可以按层级比较XML文件的差异,可以使用lxml包中的diff函数,允许指定差异深度,而深度需要根据两个XML文件的差异而定。另外还可以使用difflib库中的diff()函数,它返回XML文件树形结构差异,可以轻松实现层级比对。 参考技术A 这些XML文件包含数千个小对象。文件本身的大小约为5 MB。棘手的是,这两个文件中只有极少数条目不同,我只需要处理不同的信息。 换句话说:我需要有效率(!)找出哪些条目已更改或已添加。不幸的是,XML文件还包含一些我根本不关心的可选条目。在

我考虑了以下解决方案:

将这两个文件解析为DOM树并在循环中比较它们
将两个文件解析为集合,并使用如下运算符设置差分在
尝试将一些处理交给一些linux工具,比如grep和diff
这里有没有人有这种方法的实践经验,并能为我指明前进的方向

Python:找出整数列表是不是一致

【中文标题】Python:找出整数列表是不是一致【英文标题】:Python: find out whether a list of integers is coherentPython:找出整数列表是否一致 【发布时间】:2013-08-08 16:56:10 【问题描述】:

我试图找出整数列表是连贯的还是“一气呵成”,这意味着两个相邻元素之间的差必须恰好是一个,并且数字必须单调增加。我found 一种巧妙的方法,我们可以按列表中的数字减去列表中元素的位置进行分组——当数字不一致时,这种差异会发生变化。显然,当序列不包含间隙或重复时,应该只有一组。

测试:

>>> l1 = [1, 2, 3, 4, 5, 6]
>>> l2 = [1, 2, 3, 4, 5, 7]
>>> l3 = [1, 2, 3, 4, 5, 5]
>>> l4 = [1, 2, 3, 4, 5, 4]
>>> l5 = [6, 5, 4, 3, 2, 1]
>>> def is_coherent(seq):
...     return len(list(g for _, g in itertools.groupby(enumerate(seq), lambda (i,e): i-e))) == 1
... 
>>> is_coherent(l1)
True
>>> is_coherent(l2)
False
>>> is_coherent(l3)
False
>>> is_coherent(l4)
False
>>> is_coherent(l5)
False

效果很好,但我个人觉得这个解决方案考虑到问题的简单性,有点过于复杂了。你能想出一个更清晰的方法来达到同样的效果而不显着增加代码长度吗?

编辑:答案摘要

根据下面给出的答案,解决方案

def is_coherent(seq):
    return seq == range(seq[0], seq[-1]+1)

显然赢了。对于小列表(10^3 个元素),它比 groupby 方法快 10 倍,(在我的机器上)仍然比下一个最佳方法(使用 izip_longest)快四倍。它具有最差的缩放行为,但即使对于具有 10^8 个元素的大型列表,它仍然比第二好的方法快两倍,这也是基于 izip_longest 的解决方案。

timeit获取的相关时序信息:

Testing is_coherent_groupby...
   small/large/larger/verylarge duration: 8.27 s, 20.23 s, 20.22 s, 20.76 s
   largest/smallest = 2.51
Testing is_coherent_npdiff...
   small/large/larger/verylarge duration: 7.05 s, 15.81 s, 16.16 s, 15.94 s
   largest/smallest = 2.26
Testing is_coherent_zip...
   small/large/larger/verylarge duration: 5.74 s, 20.54 s, 21.69 s, 24.62 s
   largest/smallest = 4.28
Testing is_coherent_izip_longest...
   small/large/larger/verylarge duration: 4.20 s, 10.81 s, 10.76 s, 10.81 s
   largest/smallest = 2.58
Testing is_coherent_all_xrange...
   small/large/larger/verylarge duration: 6.52 s, 17.06 s, 17.44 s, 17.30 s
   largest/smallest = 2.65
Testing is_coherent_range...
   small/large/larger/verylarge duration: 0.96 s, 4.14 s, 4.48 s, 4.48 s
   largest/smallest = 4.66

测试代码:

import itertools
import numpy as np
import timeit


setup = """
import numpy as np
def is_coherent_groupby(seq):
    return len(list(g for _, g in itertools.groupby(enumerate(seq), lambda (i,e): i-e))) == 1

def is_coherent_npdiff(x):
    return all(np.diff(x) == 1)

def is_coherent_zip(seq):
    return all(x==y+1 for x, y in zip(seq[1:], seq))

def is_coherent_izip_longest(l):
    return all(a==b for a, b in itertools.izip_longest(l, xrange(l[0], l[-1]+1)))

def is_coherent_all_xrange(l):
    return all(l[i] + 1 == l[i+1] for i in xrange(len(l)-1))

def is_coherent_range(seq):
    return seq == range(seq[0], seq[-1]+1)


small_list = range(10**3)
large_list = range(10**6)
larger_list = range(10**7)
very_large_list = range(10**8)
"""


fs = [
    'is_coherent_groupby',
    'is_coherent_npdiff',
    'is_coherent_zip',
    'is_coherent_izip_longest',
    'is_coherent_all_xrange',
    'is_coherent_range'
    ]


for n in fs:
    print "Testing %s..." % n
    t1 = timeit.timeit(
        '%s(small_list)' % n, 
        setup,
        number=40000
        )      
    t2 = timeit.timeit(
        '%s(large_list)' % n, 
        setup,
        number=100
        )     
    t3 = timeit.timeit(
        '%s(larger_list)' % n, 
        setup,
        number=10
        )
    t4 =  timeit.timeit(
        '%s(very_large_list)' % n, 
        setup,
        number=1
        )
    print "   small/large/larger/verylarge duration: %.2f s, %.2f s, %.2f s, %.2f s" % (t1, t2, t3, t4)
    print "   largest/smallest = %.2f" % (t4/t1)

测试机:

Linux 3.2.0 (Ubuntu 12.04) Python 2.7.3 (gcc 4.1.2) 使用英特尔编译器构建的 numpy 1.6.2 CPU:E5-2650 @ 2.00GHz 24 GB 内存

【问题讨论】:

【参考方案1】:

怎么样

sorted_list = sorted(my_list)
return sorted_list == range(sorted_list[0],sorted_list[-1]+1)

或者如果它只有在已经排序的情况下是连贯的

return my_list == range(my_list[0],my_list[-1]+1)

如果您使用的是 python 3,则需要 list(range(...))

【讨论】:

那你就不能list == range(list[0], list[-1]+1)吗? :) 您不需要排序或任何minmax。单调性是要求!见:>>> l1 == range(l1[0], l1[-1]+1) -> True——我喜欢这种方法,现在我们只需要考虑性能:) 是的,我不知道...这取决于您如何定义连贯啊,您在编辑中添加了更多示例,我看到了:) ... 对于 Python 3,您需要将 range() 包装在 list() 中;也许值得一提。 @JoranBeasley:我在问题中将其定义为“意味着两个相邻元素之间的差必须恰好是一个并且数字必须单调增加”。【参考方案2】:

除非我忽略了您的示例中的某些内容,否则这个更简单的解决方案实际上更短。

>>> l1 = [1, 2, 3, 4, 5, 6]
>>> l2 = [1, 2, 3, 4, 5, 7]
>>> l3 = [1, 2, 3, 4, 5, 5]
>>> l4 = [1, 2, 3, 4, 5, 4]
>>> l5 = [6, 5, 4, 3, 2, 1]
>>> 
>>> def is_coherent(seq):
...     return seq == range(seq[0], seq[0]+len(seq), 1)
... 
>>> is_coherent(l1)
True
>>> is_coherent(l2)
False
>>> is_coherent(l3)
False
>>> is_coherent(l4)
False
>>> is_coherent(l5)
False
>>> 

一些基本性能测试的结果似乎表明这种方法明显更快(我已将您的示例添加为is_coherent2):

Carl > python -m timeit -s 'from t import is_coherent, l1' 'is_coherent(l1)'
1000000 loops, best of 3: 0.782 usec per loop
Carl > python -m timeit -s 'from t import is_coherent, l3' 'is_coherent(l3)'
1000000 loops, best of 3: 0.796 usec per loop
Carl > python -m timeit -s 'from t import is_coherent2, l1' 'is_coherent2(l1)'
100000 loops, best of 3: 4.54 usec per loop
Carl > python -m timeit -s 'from t import is_coherent2, l3' 'is_coherent2(l3)'
100000 loops, best of 3: 4.93 usec per loop

【讨论】:

与@JoranBeasley 建议的基本相同——与基于 itertools 的解决方案相比,您希望它如何执行?您想执行一些基准测试吗? 更新了一些 timeit 示例。【参考方案3】:

如果您正在寻找 numpy 解决方案:

import numpy as np

def is_coherent(x):
    return all(np.diff(x) == 1)

is_coherent(np.array([1,2,3,4,5]))
Out[39]: True

is_coherent(np.array([1,2,3,4,8]))
Out[40]: False

【讨论】:

【参考方案4】:
def is_coherent(seq):
    return all(x==y+1 for x, y in zip(seq[1:], seq))

【讨论】:

去掉括号,你就可以把你的列表推导变成生成器推导。【参考方案5】:

这会短路并且不会创建额外的列表,因此对于测试非常大的列表很有用。

def is_coherent(l):
    return all(a==b for a, b in izip_longest(l, xrange(l[0], l[-1]+1)))

或者

def is_coherent(l):
    return all(l[i] + 1 == l[i+1] for i in xrange(len(l)-1))

【讨论】:

这可能会比我的解决方案更快,内存效率更高 我收回这比我的方法慢得多......但可能更好的内存使用,所以仍然应该适用于非常大的列表(如大于 1000 万) @JoranBeasley:内存效率更高?是的。但是更快?可能不是因为即使对于相对较大的列表,列表创建速度也快得离谱。 @JoranBeasley:另外,比较两个列表是否相等是在 C 中实现的。 基于izip_longest 的解决方案是最好的、有趣的解决方案(请参阅我的答案中的编辑)!【参考方案6】:

我不知道 python,但我知道它的功能,所以这里有一个小循环函数,如果你更改正确 python 的语法,它将执行此操作。

伪代码

def is_coherent(seq):
     for x in xrange(1, len(seq)-1):
        if (seq[x+1]-seq[x] != 1)  return false;   
     return true

【讨论】:

以上是关于python按层级找出xml文件的差异的主要内容,如果未能解决你的问题,请参考以下文章

Maven配置文件settings.xml详解

python 分别使用Python中自带的xml.etree.ElementTree和第三方LXML来生成一个按首字母归类的城市列表XML文件。

Python爬虫编程思想(76): 读取与搜索XML文件

Python爬虫编程思想(76): 读取与搜索XML文件

一种比较两个 XML 文件并创建另一个具有差异的文件的快速方法

如何区分两个 .xml 文件并在 XSLT 中存储差异? [关闭]