我试图解析一个json文件,以便为artifactory实例创建一个删除列表。
我喜欢用两个字段对它们进行分组:repo和path。然后保留每个分组的两个对象与最近的"修改" timestamp并删除json文件中的所有其他对象。
所以,原始文件看起来像这样:
{
"results": [
{
"repo": "repo1",
"path": "docker_image_dynamic",
"size": 3624,
"modified": "2016-10-01T06:22:16.335Z"
},
{
"repo": "repo1",
"path": "docker_image_dynamic",
"size": 3646,
"modified": "2016-10-01T07:03:58.465Z"
},
{
"repo": "repo1",
"path": "docker_image_dynamic",
"size": 3646,
"modified": "2016-10-01T07:06:36.522Z"
},
{
"repo": "repo2",
"path": "docker_image_static",
"size": 3624,
"modified": "2016-09-29T20:31:44.054Z"
}
]
}
应该成为这个:
{
"results": [
{
"repo": "repo1",
"path": "docker_image_dynamic",
"size": 3646,
"modified": "2016-10-01T07:03:58.465Z"
},
{
"repo": "repo1",
"path": "docker_image_dynamic",
"size": 3646,
"modified": "2016-10-01T07:06:36.522Z"
},
{
"repo": "repo2",
"path": "docker_image_static",
"size": 3624,
"modified": "2016-09-29T20:31:44.054Z"
}
]
}
答案 0 :(得分:2)
这应该这样做:
.results |= [group_by({repo,path})[] | sort_by(.modified)[-2:][]]
按repo
和path
对数组中的项目进行分组后,按modified
对组进行排序,并保留已排序组的最后两项。然后再次拆分组并将它们收集到一个新阵列中。
答案 1 :(得分:1)
这是一个更麻烦的解决方案,它使用 reduce 来维护一个临时对象,其中包含每个repo
和path
的最后两个值。除非输入包含(repo,path)的每个组合的大量条目,否则它可能不会比Jeff的解决方案更好:
{
results: [
reduce .results[] as $r (
{} # temporary object
; (
getpath([$r.repo, $r.path]) # keep the latest two
| . + [$r] # elements for each
| sort_by(.modified)[-2:] # repo and path in a
) as $new # temporary object
| setpath([$r.repo, $r.path]; $new) #
)
| .[] | .[] | .[] # extract saved elements
]
}
答案 2 :(得分:1)
@ jq170727对使用group_by
的潜在低效率提出了一个很好的观点,因为group_by
涉及排序。在实践中,排序可能太快而无关紧要,但如果关注,我们可以非常轻松地定义我们自己的无排序版本group_by
:
# sort-free variant of group_by/1
# f must always evaluate to a string.
# Output: an object
def GROUP_BY(f): reduce .[] as $x ({}; .[$x|f] += [$x] );
@ JeffMercado的解决方案现在可以在tojson
的帮助下使用,如下所示:
.results |= [GROUP_BY({repo,path}|tojson)[] | sort_by(.modified)[-2:][]]
为了避免调用tojson
,我们可以调整以上内容以产生以下更快的解决方案:
def GROUP_BY(f;g): reduce .[] as $x ({}; .[$x|f][$x|g] += [$x]);
.results |= [GROUP_BY(.repo;.path)[][] | sort_by(.modified)[-2:][]]
答案 3 :(得分:1)
除了评论之外,这里有一个更简洁(更jq-esque(*))的方式来表达@ jq170727的解决方案:
.results |= [reduce .[] as $r ( {};
.[$r.repo][$r.path] |= ((.+[$r]) | sort_by(.modified)[-2:]))
| .[][]]
(*)特别没有getpath,setpath或$ new;并且|=
减少了冗余。