python - 通过读取 XML 文件的内容创建 lambda 函数
问题描述
我需要在 Python 中基于 XML 内容动态创建 lambda 函数,以便过滤掉一些数据。
以下是 lambda 函数的条件如何以 XML 格式排列的示例:
<conditions>
<or>
<and>
<eq>
<field>is_hazardous</field>
<literal>1</literal>
</eq>
<eq>
<field>is_refrigeration</field>
<literal>0</literal>
</eq>
<not-eq>
<field>year</field>
<literal>2005</literal>
</not-eq>>
<not-eq>
<field>material</field>
<literal>plastic</literal>
</not-eq>>
</and>
<eq>
<field>is_active</field>
<literal>1</literal>
</eq>>
</or>
</conditions>
- 条件标签将始终相同。
- tags字段和文字将始终是eq和/或not-eq的孩子。
这是一组 CSV 格式的数据:
is_hazardous,is_refrigeration,year,material,is_active
1,0,2006,metal,1
1,0,2005,metal,0
我需要实现的是:
def eval_data(x):
return (
(
(x['is_hazardous'] == 1) and
(x['is_refrigeration'] == 0) and
(x['year'] != 2005) and (x['material'] != 'plastic'))
or (x['is_active'] == 1)
)
df = pd.read_csv('sample.csv')
df['check'] = df.apply(lambda x: eval_data(x),
axis = 1)
此函数应为第一行输出True,为第二行输出False。
如何通过读取 XML 文件的内容动态创建eval_data函数的返回表达式?
解决方案
这是一个相当有趣的问题。我已经实现了 eq 和 or 作为示例,您可以实现 neq 和 and。
import xml.etree.ElementTree as ET
from typing import List
class Evaluable:
def eval(self, *args, **kwargs):
""" returns the outcome of the operation """
raise NotImplemented
class OR(Evaluable):
def __init__(self, n):
self.children: List[Evaluable] = [NODE.parse(child) for child in n]
def eval(self, *args, **kwargs):
""" performs or operation for the children """
return any([c.eval(*args, **kwargs) for c in self.children])
class EQ(Evaluable):
def __init__(self, n):
# parse field name
self.field = n.find("field")
if self.field is None:
raise ValueError("field not found")
self.field = self.field.text
# parse literal value as str
self.literal = n.find("literal")
if self.literal is None:
raise ValueError("literal not found")
self.literal = self.literal.text
def eval(self, *args, evaluation_params: dict = None, **kwargs):
""" performs eq operation for the children """
return evaluation_params[self.field] == self.literal
class NODE(Evaluable):
@classmethod
def parse(cls, n) -> Evaluable:
if n.tag == "eq":
return EQ(n)
if n.tag == "or":
return OR(n)
sample_xml = """<conditions>
<or>
<or>
<eq>
<field>is_hazardous</field>
<literal>1</literal>
</eq>
<eq>
<field>is_refrigeration</field>
<literal>0</literal>
</eq>
<eq>
<field>year</field>
<literal>2005</literal>
</eq>>
<eq>
<field>material</field>
<literal>plastic</literal>
</eq>>
</or>
<eq>
<field>is_active</field>
<literal>1</literal>
</eq>>
</or>
</conditions>"""
root = ET.fromstring(sample_xml)
node = NODE.parse(root[0])
parser = lambda x: node.eval(evaluation_params=x)
print(parser({"is_hazardous": "1",
"is_refrigeration": "0",
"year": "2006",
"material": "metal",
"is_active": "1"}))
推荐阅读
- angular - 无法为离子选择多预分配值
- r - 重新编码 R 数据框中的多列
- html - 带有表格和动态数字或行的引导手风琴
- constraints - ASN.1:SIZE 约束能否用于约束 SEQUENCE(不是 SEQUENCE OF)
- scala - Gatling:将 findAll 转换为排序列表
- graphql - 中继突变后如何更新商店?
- python - 如何使用 Python 函数导出和调用(Pickle、Joblib、Dump)?
- java - canvas S刷新Android Studio的问题
- react-native - 如何使用 Expo 通过 API 访问所有图像库
- laravel - 如何在没有全局目录的情况下初始化 git?