jq:将对象数组转换为对象

jq: translate array of objects to object

我收到 curl 的回复,格式如下:

[
  {
    "list": [
      {
        "value": 1,
        "id": 12
      },
      {
        "value": 15,
        "id": 13
      },
      {
        "value": -4,
        "id": 14
      }
    ]
  },
  ...
]

给定这样的 ID 之间的映射:

{
  "12": "newId1",
  "13": "newId2",
  "14": "newId3"
}

我想做这个:

[
  {
    "list": {
      "newId1": 1,
      "newId2": 15,
      "newId3": -4,
    }
  },
  ...
]

这样我就得到了从 id 到值的映射(并且在这个过程中我想重新映射 id)。

我已经为此工作了一段时间,但每次都遇到死胡同。

注意:如有必要,我可以使用 Shell 等来执行循环。

编辑:这是我目前开发的一个版本:

jq '[].list.id = ($mapping.[] | select(.id == key)) | del(.id)' -M --argjson "mapping" "$mapping"

我不认为它是最好的,但我正在寻找是否可以找到更接近我需要的旧版本。

[编辑:以下回复是对问题的回答,它描述了 (a) 如下所示的映射,以及 (b) 具有以下形式的输入数据:

[
  {
    "list": [
      {
        "value": 1,
        "id1": 12
      },
      {
        "value": 15,
        "id2": 13
      },
      {
        "value": -4,
        "id3": 14
      }
    ]
  }
]

编辑结束]

在下文中,我将假设映射可通过以下函数获得,但这是一个无关紧要的假设:

def mapping: {
  "id1": "newId1",
  "id2": "newId2",
  "id3": "newId3"
} ;

以下 jq 过滤器将产生所需的输出:

map( .list
     |= (map( to_entries[]
              | (mapping[.key]) as $mapped
              | select($mapped)
              | {($mapped|tostring): .value} )
         | add) )

给猫剥皮的方法有很多。我会这样做:

.[].list |= reduce .[] as $i ({};
    ($i.id|tostring) as $k
      | (select($mapping | has($k))[$mapping[$k]] = $i.value) // .
)

您只需通过单独的文件或参数提供映射。

$ cat program.jq
.[].list |= reduce .[] as $i ({};
    ($i.id|tostring) as $k
      | (select($mapping | has($k))[$mapping[$k]] = $i.value) // .
)

$ cat mapping.json
{
  "12": "newId1",
  "13": "newId2",
  "14": "newId3"
}

$ jq --argfile mapping mapping.json -f program.jq input.json
[
  {
    "list": {
      "newId1": 1,
      "newId2": 15,
      "newId3": -4
    }
  }
]

这是修改后的问题的无减少解决方案。

在下文中,我将假设映射可通过以下函数获得,但这是一个无关紧要的假设:

def mapping:
{
  "12": "newId1",
  "13": "newId2",
  "14": "newId3"
} ;


map( .list
     |= (map( mapping[.id|tostring] as $mapped
              | select($mapped)
              |  {($mapped): .value} )
         | add) )

"select" 是为了安全起见(即,它检查所考虑的 .id 是否确实已映射)。通过编写 {($mapped|tostring): .value}.

来确保 $mapped 是一个字符串可能也是合适的