shell 如何使用jq通过使用子值对象的键对json对象进行分组

o2rvlv0m  于 12个月前  发布在  Shell
关注(0)|答案(3)|浏览(173)

我有一个JSON文件,格式是

{
  "hello": [
    {
      "name": "var1",
      "value": "1234"
    },
    {
      "name": "var2",
      "value": "2356"
    },
    {
      "name": "var3",
      "value": "2356"
    }
  ],
  "hi": [
    {
      "name": "var1",
      "value": "3412"
    },
    {
      "name": "var2",
      "value": "2563"
    },
    {
      "name": "var3",
      "value": "4256"
    }
  ],
  "bye": [
    {
      "name": "var1",
      "value": "1294"
    },
    {
      "name": "var2",
      "value": "8356"
    },
    {
      "name": "var3",
      "value": "5356"
    }
  ]
}

我想把这个对象转换成这种格式

{
  "output": [
    {
      "var1": {
        "hello": "1234",
        "hi": "3412",
        "bye": "1294"
      }
    },
    {
      "var2": {
        "hello": "2356",
        "hi": "2563",
        "bye": "8356"
      }
    },
    {
      "var3": {
        "hello": "2356",
        "hi": "4256",
        "bye": "5356"
      }
    }
  ]
}

到目前为止,我已经尝试了多种方法使用to_entries和jq中的map函数来创建输出变量jq 'to_entries | map(.value[]| . += {"key_v" : (.key)} )' input.json > output.json中的内容,这是我最接近的解决方案。

  • 提取键并添加到对象的键值对中
  • 使用map(select())来按键分组,但我在这两个步骤中都得到了错误,例如不能用字符串名称或字符串值索引数组。
0sgqnhkj

0sgqnhkj1#

它不会赢得选美比赛,但它的工作:

with_entries(.value |= from_entries)
| with_entries(.key as $key | .value[] |= {($key):.})
| reduce .[] as $item ({}; . * $item)
| {output: to_entries | map({(.key):.value})}

通过对with_entries的单个调用:

with_entries(.key as $key | .value |= (from_entries | map_values({($key):.})))
| reduce .[] as $item ({}; . * $item)
| {output: to_entries | map({(.key):.value})}

输出量:

{
  "output": [
    {
      "var1": {
        "hello": "1234",
        "hi": "3412",
        "bye": "1294"
      }
    },
    {
      "var2": {
        "hello": "2356",
        "hi": "2563",
        "bye": "8356"
      }
    },
    {
      "var3": {
        "hello": "2356",
        "hi": "4256",
        "bye": "5356"
      }
    }
  ]
}
uelo1irk

uelo1irk2#

如果使用以下面向流的“聚结”函数,则容易获得简单的解:

# s is assumed to be a stream of objects for which
# the values for each distinct key are summable.
# Output: a single object formed by adding 
# the $v values of each distinct key.
def coalesce(s):
  reduce (s | to_entries[]) as {key: $k, value: $v} ({};
    .[$k] += $v);

现在的解决方案很简单:

coalesce(to_entries[]
         | .key as $key
         | .value[]
         | {(.name): {($key): .value}})
| {output: [.]}
wvt8vs2t

wvt8vs2t3#

这会产生预期的结果:

{ output:
    to_entries |
    map(.key as $key|.value|map(.nn=.name|.name=$key)) |
    add |
    group_by(.nn) |
    map({(first|.nn) : from_entries})
}

相关问题