gpt4 book ai didi

python - 使用 JMESPath 基于另一个查询结果过滤列表

转载 作者:行者123 更新时间:2023-12-05 02:09:34 24 4
gpt4 key购买 nike

有一个如下所示的对象:

{
"pick": "a",
"elements": [
{"id": "a", "label": "First"},
{"id": "b", "label": "Second"}
]
}

如何检索 elements 列表中的项目,其中 id 等于 pick 的值?

我正在尝试类似的东西:

elements[?id == pick]

但是,显然,比较器右侧的表达式是相对于根据我的过滤器表达式测试的对象进行评估的。

我怎样才能达到我想要的?如果这不可能开箱即用,您对我应该从哪里开始扩展 JMESPath 有什么建议吗?谢谢!

最佳答案

不幸的是,JMESPath 不允许引用父元素。

为了规避这个限制,在这个简单的例子中,你可以:

  • 读取第一个查询中的pick属性,
  • 使用刚刚读取的值创建第二个查询,
  • 在第二个查询中阅读想要的内容。

实际上,感谢 f-strings,最后两个步骤可以在一条指令,所以代码可以是:

pck = jmespath.search('pick', dct)
jmespath.search(f'elements[?id == `{pck}`]', dct)

其中 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"}
]
}
}

首先要做的是将 dct 转换为 Pandas DataFrame:

import pandas as pd
df = pd.DataFrame.from_dict(dct, orient='index')

结果(以“缩短”形式打印)是:

   pick                                           elements
x1 a [{'id': 'a', 'label': 'First_a'}, {'id': 'b', ...
x2 b [{'id': 'a', 'label': 'First_b'}, {'id': 'b', ...

说明(如果您没有Pandas 经验):

  • x1, x2, ... - 索引列 - 取自第一级键的值在 dct 中。
  • pick - 包含(毫不奇怪)pick 元素的列,
  • elements - 包含 elements 的列(现在每个单元格都包含整个列表)。

这个形状不是很有用,所以让我们展开元素列:

df = df.explode('elements')

现在 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'}

这个形状更接近我们需要的:每个源行都被分解成几行,每一行都有来自初始列表的单独项。

还有一件事要做,即创建一个包含 id 值的列,稍后将与 pick 列进行比较。要做到这一点运行:

df['id'] = df.elements.apply(lambda dct: dct['id'])

现在 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

要获得最终结果,您应该:

  • 使用 pick column == id 选择行,
  • 只取 elements 列(连同关键列,但这个细节Pandas 让您开箱即用。

实现的代码是:

df.query('pick == id').elements

给予:

x1     {'id': 'a', 'label': 'First_a'}
x2 {'id': 'b', 'label': 'Second_b'}

Pandas 的说法中,它是一个 Series(比方说一个包含每个元素的列表用索引“标记”。

现在您可以将其转换为字典或您想要的任何内容。

关于python - 使用 JMESPath 基于另一个查询结果过滤列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59714814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com