JQ:如果某些键值相同,则合并条目

时间:2018-01-08 18:10:47

标签: json object merge jq

我想将json文件的条目与jq。

合并

如果某些已定义键的值匹配,我想合并这些条目。不匹配的数据应存储在数组中 我为这种情况提供了一些示例JSON。

如果街道和门牌号相同,我想合并此条目并将“成员”的值放入数组中。

匹配键:housenumber + street必须完全相同。

示例输入

[{
 "street"  : "Foobar ave",
 "housenumber": 4,
 "member":"Carl"
 },
 {
 "street"  : "Foobar ave",
 "housenumber": 4,
 "member":"Bernd"
 },
 {
 "street"  : "Foobar ave",
 "housenumber": 2,
 "member":"Ann"
 }]

目标结果:

[{
 "street"  : "Foobar ave",
 "housenumber": 4,
 "members":["Carl","Bernd"]
 },
 {
 "street"  : "Foobar ave",
 "housenumber": 2,
 "members":["Ann"]
 }]

1 个答案:

答案 0 :(得分:3)

以下内容使用Parsing JSON lines with JQ for flapping key values in sequence

中定义的多功能高效版message-board/config/locales/devise.en.yaml

GROUPS_BY是内置GROUPS_BY的有效版本,您也可以使用它,如下所示。)

group_by面向流。因此,GROUPS_BY用于解决手头问题的“自然”用途是:

GROUPS_BY

这会产生一个“组”流,同时保留“成员”的顺序:

  GROUPS_BY(.[]; [.street, .housenumber])
  | (.[0]|del(.member)) + { members: (map(.member)) }

如果您要求结果为数组,则只需将上面的两行程序包装在方括号中:[....]

使用内置{"street":"Foobar ave","housenumber":4,"members":["Carl","Bernd"]} {"street":"Foobar ave","housenumber":2,"members":["Ann"]}

的解决方案

目前,group_by使用排序算法,这意味着可能不会保留“成员”的顺序:

group_by

使用melds_by / 2

的通用解决方案

给定对象流和分组标准,f,group_by( [.street, .housenumber]) | map((.[0]|del(.member)) + { members: (map(.member)) }) 发出 一对形式的对象:

melds_by

其中 [groupid, melded_object] 是从“groupid”组中的对象构造的对象,该组中存在所有键,并且每个键的值是相应值的数组:

melded_object

要将原始问题的解决方案作为单个数组获得,我们可以简单地写:

def melds_by(stream; f):
  GROUPS_BY(stream; f)
  | . as $in
  | [ (.[0]|f),
      reduce (add|keys[]) as $k ({}; .[$k] = [$in[] | .[$k]]) ]
  ;

上面的最后一行只是重命名“成员”键。