编写此 elementTree 搜索操作的更好方法?
Better way to write this elementTree search operation?
我正在编写 python 脚本来研究期权定价。我在 XSL 中做了很多预处理并输出一个 XML 文件,该文件使用 elementTree api.
读入我的 python 脚本
xml的结构如下:
根 XML 节点的子节点是股票元素,每个股票一个。
<stock>
元素的子元素是日元素,每天一个。
<day>
个元素的子元素是 f 个元素,一个对应于我查看的每个前瞻日。
f 元素有一些属性,"days" 表示当天的前进时间,"change" 表示当天股价的变化。
由于股票不是每天都在交易,所以“@days”的顺序有空缺。例如,与星期四关联的日元素可能如下所示:
<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.
不幸的是,如果您尝试执行 f[@days = X].get('change') 如果没有 f 元素且 days = X,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 对象。
因为对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
而不是.get
,尝试.find
with an XPath,其中returns 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]]
这也意味着你可以把你的整个函数写成一个可怕的 one-liner 像这样(未经测试):
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
。
我正在编写 python 脚本来研究期权定价。我在 XSL 中做了很多预处理并输出一个 XML 文件,该文件使用 elementTree api.
读入我的 python 脚本xml的结构如下:
根 XML 节点的子节点是股票元素,每个股票一个。
<stock>
元素的子元素是日元素,每天一个。
<day>
个元素的子元素是 f 个元素,一个对应于我查看的每个前瞻日。
f 元素有一些属性,"days" 表示当天的前进时间,"change" 表示当天股价的变化。
由于股票不是每天都在交易,所以“@days”的顺序有空缺。例如,与星期四关联的日元素可能如下所示:
<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.
不幸的是,如果您尝试执行 f[@days = X].get('change') 如果没有 f 元素且 days = X,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 对象。
因为对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
而不是.get
,尝试.find
with an XPath,其中returns 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]]
这也意味着你可以把你的整个函数写成一个可怕的 one-liner 像这样(未经测试):
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
。