从由jq中的属性键控的对象流中创建对象

时间:2018-10-22 11:08:24

标签: json jq

这是关于命令行json处理器jq的问题。关于javascript或jQuery或名称中带有js和qs的其他任何内容不是

我输入的数据如下:

VBoxHeadless

我想要这样的输出:

{ "id": "person1", "name": "wilma", "age": "quite old"}
{ "id": "person2", "name": "fred"}
{ "id": "person1", "name": "betty", "x": "extra"}

我尝试了各种事情!

例如

{
   "person1": { "name": "betty", "age": "quite old", "x": "extra" },
   "person2": { "name": "fred" }
}

给予

jq -s '.[] | { (.id) : . }' <data

除了输出一个对象流而不是一个对象流之外,它在那里。我需要将所有这些对象合并在一起。

jqplay.org example

我也尝试过使用{ "person1": { "id": "person1", "name": "wilma", "age": "quite old" }} { "person2": { "id": "person2", "name": "fred" }} { "person1": { "id": "person1", "name": "betty", "x": "extra" }} 合并每个项目,但仍然会产生一个流。 https://jqplay.org/s/lh6QUQ0DO4

2 个答案:

答案 0 :(得分:1)

您可以按以下方式调整尝试:

jq -s 'map({ (.id) : . }) | add' <data

但是,将inputsreduce与-n命令行选项一起使用而不是-s会更有效。

当然,使用这种方法会带来碰撞的风险。

您可能还想添加del(.id)

答案 1 :(得分:1)

啊!我懂了!或者我有一个解决方案-如果有更好的方法,请发表。

jq -s '[group_by(.id)[]| add | { (.id) : . } ]|add' <data

https://jqplay.org/s/BfAdRBZUMW

  1. group_by通过.id值对输入进行分组,并生成一个数组数组-内部数组是与id匹配的值。

  2. 对于每个组,将内部数组传递到add,由于内部数组中的对象是对象,因此它们会合并。

  3. 剩下2个项目数组。我们将其提供给对象构造器,该构造器将id作为键,将整个项目作为值。仍然留下了一系列物品。

  4. 外部[](从模式开始处开始)说,将所有内容都接受并将其提供给add(再次),它将合并在(3)中创建的最终对象。

它可以工作,但是可能会有更干净的方法。

编辑

这很丑陋,但产生的结果相同,在9MB的数据集上,速度提高了约24%。

jq -s 'reduce [.[]|{ (.id) : . }][] as $item ({}; . * $item )' <data

这使用reduce <list> as <$var> (<initiation>; <iteration>)(从一个空对象{}开始,并使用合并运算符*(从传入项目.开始)来创建输出。令我惊讶的是它的速度更快,但是我知道group_by可以完成排序,所以我认为这是额外的时间成本。