编写此elementTree搜索操作的更好方法是什么?

时间:2016-01-10 11:51:22

标签: python python-2.7 elementtree

我正在研究python脚本来研究期权定价。我在XSL中做了很多预处理,并使用elementTree api输出一个读入我的python脚本的XML文件。

xml具有以下结构:
根XML节点的子节点是库存元素,每个库存一个 <stock>元素的子元素是日元素,每天一个元素 <day>元素的子元素是f元素,每个前进日都有一个元素 f元素有一些属性,“天”表示当天前进多远,“变化”表示当天股票价格的变化。

由于股票每天不交易,“@days”的顺序有差距。例如,与星期四关联的day元素可能如下所示:

<day [info in attributes>
<f days="1" change="-3.1"/>
<f days="4" change="-1"/>
<f days="5" change="0.4"/>
<f days="6" change="1.1"/>
...
</day>

现在,我正在尝试查找历史数据并查找@days = X的实例,其中X是输入。但是如果一个给定的<day>元素没有这样的一天,我会选择一个f元素,其中@days = X - 1.如果它没有其中一个,我会寻找一个f元素@days = X + 1。

不幸的是,如果你没有使用天数= X的f元素,如果你试图做f [@days = X] .get('change'),elementTree库会抛出一个错误。所以我现在这样做了以下方式:

Changes = []
for day in Test_Stock:
    forward_days = [int(f.get('days')) for f in day]
    if X in forward_days:
        expiry_day = [f for f in day if int(f.get('days')) == X]
        Changes.append(float(expiry_day[0].get('change')))
    elif (X - 1) in forward_days:
        proxy_day = [f for f in day if int(f.get('days')) == (X - 1)]
        Changes.append(float(proxy_day[0].get('change')))
    elif (X + 1) in forward_days:
        proxy_day = [f for f in day if int(f.get('days')) == (X + 1)]
        Changes.append(float(proxy_day[0].get('change')))

这给出了预期的结果,但我希望有一种更简单的方法可以做到这一点,并希望知道如何更好地使用elementTree对象。

2 个答案:

答案 0 :(得分:1)

因为X,X-1和X + 1的处理相同,所以可以使用如下循环:

Changes = []
for day in Test_Stock:
    forward_days = [int(f.get('days')) for f in day]
for x in [X,X-1,X+1]:
    if x in forward_days:
        expiry_day = [f for f in day if int(f.get('days')) == x]
        Changes.append(float(expiry_day[0].get('change')))
        break

答案 1 :(得分:0)

而不是.get,请使用.find代替XPath,如果没有匹配的元素,则返回None,而不是异常。

使用find可让ElementTree进行搜索,而无需手动过滤[f for f in int(f.get('days')) == x]

因此,对于每个day,您想要的f元素(如果存在)将是此列表中的第一个非None项:

[day.find("f[@days='%d']" % index)
 for index in [X, X - 1, X + 1]]

这也意味着你可以把你的整个功能写成像这样可怕的单行(未经测试):

Changes = [float(d[0].get('change'))
           for d in [islice(ifilter(len, (day.find("f[@days='%d']" % candidate)
                                          for candidate in [X, X - 1, X + 1])),
                            1)
                     for day in Test_Stock]
           if d]

但请不要这样做。

然而,绝对要研究.find