Vic*_*tor 3 python pandas jmespath
拥有一个如下所示的对象:
{
"pick": "a",
"elements": [
{"id": "a", "label": "First"},
{"id": "b", "label": "Second"}
]
}
Run Code Online (Sandbox Code Playgroud)
如何检索elements列表中id等于 值的项目pick?
我正在尝试类似的事情:
elements[?id == pick]
Run Code Online (Sandbox Code Playgroud)
但是,显然,比较器右侧的表达式是相对于根据我的过滤器表达式测试的对象进行评估的。
我怎样才能实现我想要的?如果这不可能开箱即用,您对我应该从哪里开始扩展 JMESPath 有什么建议吗?谢谢你!
不幸的是,JMESPath不允许引用父元素。
要规避此限制,在这个简单的情况下,您可以:
实际上,由于f-strings,最后两个步骤可以在一条指令中执行,因此代码可以是:
pck = jmespath.search('pick', dct)
jmespath.search(f'elements[?id == `{pck}`]', dct)
Run Code Online (Sandbox Code Playgroud)
其中dct是源 JSON 对象。
如果您有更复杂的情况(例如,许多此类元素,每种情况下都有不同的选择 值),则应该使用其他工具。
一个非常有趣的选择是使用Pandas包。
假设您的源词典包含:
dct = {
"x1": {
"pick": "a",
"elements": [
{"id": "a", "label": "First_a"},
{"id": "b", "label": "Second_a"},
{"id": "c", "label": "Third_a"}
]
},
"x2": {
"pick": "b",
"elements": [
{"id": "a", "label": "First_b"},
{"id": "b", "label": "Second_b"},
{"id": "c", "label": "Third_b"}
]
}
}
Run Code Online (Sandbox Code Playgroud)
首先要做的是将dct转换为Pandas DataFrame:
import pandas as pd
df = pd.DataFrame.from_dict(dct, orient='index')
Run Code Online (Sandbox Code Playgroud)
结果(以“缩短”形式打印)是:
pick elements
x1 a [{'id': 'a', 'label': 'First_a'}, {'id': 'b', ...
x2 b [{'id': 'a', 'label': 'First_b'}, {'id': 'b', ...
Run Code Online (Sandbox Code Playgroud)
描述(如果您没有Pandas经验):
这个形状没有多大用处,所以让我们分解 元素列:
df = df.explode('elements')
Run Code Online (Sandbox Code Playgroud)
现在df包含:
pick elements
x1 a {'id': 'a', 'label': 'First_a'}
x1 a {'id': 'b', 'label': 'Second_a'}
x1 a {'id': 'c', 'label': 'Third_a'}
x2 b {'id': 'a', 'label': 'First_b'}
x2 b {'id': 'b', 'label': 'Second_b'}
x2 b {'id': 'c', 'label': 'Third_b'}
Run Code Online (Sandbox Code Playgroud)
这种形状更接近我们所需要的:每个源行都被分成几行,每行都有与初始列表不同的项目。
还有一件事要做,即创建一个包含id值的列,稍后与选择列进行比较。要执行此操作,请运行:
df['id'] = df.elements.apply(lambda dct: dct['id'])
Run Code Online (Sandbox Code Playgroud)
现在df包含:
pick elements id
x1 a {'id': 'a', 'label': 'First_a'} a
x1 a {'id': 'b', 'label': 'Second_a'} b
x1 a {'id': 'c', 'label': 'Third_a'} c
x2 b {'id': 'a', 'label': 'First_b'} a
x2 b {'id': 'b', 'label': 'Second_b'} b
x2 b {'id': 'c', 'label': 'Third_b'} c
Run Code Online (Sandbox Code Playgroud)
要获得最终结果,您应该:
执行此操作的代码是:
df.query('pick == id').elements
Run Code Online (Sandbox Code Playgroud)
给予:
x1 {'id': 'a', 'label': 'First_a'}
x2 {'id': 'b', 'label': 'Second_b'}
Run Code Online (Sandbox Code Playgroud)
用Pandas 的话说,它是一个Series(假设是一个列表,其中每个元素都用索引“标记”)。
现在您可以将其转换为字典或任何您想要的内容。
| 归档时间: |
|
| 查看次数: |
1289 次 |
| 最近记录: |