如何根据兄弟对象属性中的索引从数组中选择对象?

问题描述

我正在尝试使用与此类似的 jq 处理一些 JSON:

[
  {
    "name": "Albert"
  },{
    "name": "Brian","parentIndex": 0
  },{
    "name": "Carol",{
    "name": "Dwayne","parentIndex": 2
  },{
    "name": "Ethel","parentIndex": 3
  },{
    "name": "Francis","parentIndex": 3
  }
]

我想找到列表中具有特定 name 的所有对象,例如"Carol",然后获取它们在列表中的索引,然后根据它们的 parentIndex,使用这些索引获取列表中所有以这些对象为父对象的对象。所以,上面应该返回 Dwayne 的对象。

我知道我可以用这个得到索引:

jq '[.[] | .name == "Carol"] | indices(true)'

但不确定如何使用索引将对象从列表中取出。

解决方法

好的,在为 SO 创建更简单的测试用例时想通了。我最终不得不使用一个变量,我以前从未在 jq 中使用过。如果您知道一种无需变量的简单方法,我很乐意看到它。

以上可以解决:

jq '. as $top 
  | .[] 
  | select(
      $top[.parentIndex? | values]
        .name == "Carol"
    )' 

它在每一行的作用是:

  1. 将初始输入分配给 $top。这是必要的,因为在我们评估是否select 单个对象时,我们不再可以在没有变量的情况下访问整个数组。
  2. 将数组拆分为对象流
  3. 选择对象,如果...
  4. ... $top 数组中此对象的 parentIndex 位置处的对象...
  5. ... 的 name"Carol"
,

这是一个类似的解决方案,它只检查第一个“Carol”:

(map(.name) | index("Carol")) as $ix
| .[] 
| select( .parentIndex == $ix )
| .name

这种方法的一个显着特点 是如果有可能不止一个“卡罗尔” 如果需要同时处理所有这些可能性 方式,那么只需将上面的第一行更改为:

(map(.name) | indices("Carol"))[] as $ix