Json JQ:为输入的子集计算每个组的对象数
我需要用JQ计算每个组中的对象数,但只计算N个最近的对象 样本输入,对于N=3:Json JQ:为输入的子集计算每个组的对象数,json,stream,grouping,jq,Json,Stream,Grouping,Jq,我需要用JQ计算每个组中的对象数,但只计算N个最近的对象 样本输入,对于N=3: {"modified":"Mon Sep 25 14:20:00 +0000 2018","object_id":1,"group_id":"C"} {"modified":"Mon Sep 25 14:23:00 +0000 2018","object_id":2,"group_id":"A"} {"modified":"Mon Sep 25 14:21:00 +0000 2018","object_id":3,
{"modified":"Mon Sep 25 14:20:00 +0000 2018","object_id":1,"group_id":"C"}
{"modified":"Mon Sep 25 14:23:00 +0000 2018","object_id":2,"group_id":"A"}
{"modified":"Mon Sep 25 14:21:00 +0000 2018","object_id":3,"group_id":"B"}
{"modified":"Mon Sep 25 14:22:00 +0000 2018","object_id":4,"group_id":"A"}
预期产出:
{"A",2}
{"B",1}
我甚至没有选择一个基于日期的子集来保存对象的结构:这是我所能做到的最好的:
[
.modified |= strptime("%a %b %d %H:%M:%S %z %Y") |
.modified |= mktime |
.modified |= strftime("%Y-%m-%d %H:%M:%S")
] |
sort_by(.modified) |
.[] |
{modified, object_id, group_id}
由于某些原因,结果仍然没有分类
我也无法将这样的列表转换为数组,以便只选择N个最近的条目
在那之后,我需要以某种方式计算每组对象的数量
总的来说,我需要一个非常直观的解释,说明数组和对象列表是如何相互转换的,以及如何修改它们的一些字段,然后只提取所需的字段。不幸的是,到目前为止我发现的教程没有帮助。假设您的输入文件是:
cat file
{"modified":"Mon Sep 25 14:20:00 +0000 2018","object_id":1,"class_id":"C"}
{"modified":"Mon Sep 25 14:23:00 +0000 2018","object_id":2,"class_id":"A"}
{"modified":"Mon Sep 25 14:21:00 +0000 2018","object_id":3,"class_id":"B"}
{"modified":"Mon Sep 25 14:22:00 +0000 2018","object_id":4,"class_id":"A"}
您可以尝试以下操作:
<file jq -s '
[ .[] |
(.modified |= (strptime("%a %b %d %H:%M:%S +0000 %Y") | mktime))
] |
sort_by(.modified) | # sort using converted time
.[-3:] | # take the last 3
group_by(.class_id) | # group ids together
.[] |
{(.[0].class_id): length}' # create the object using the id name and table length
{
"A": 2
}
{
"B": 1
}
使用-s
命令行选项,该选项要求将整个输入数据放入内存中。对于非常大的数据集,这可能是不可能的
自2015年发布jq 1.5以来,有一种替代方案可用。因此,这里提出了一种使用输入的高效内存解决方案
关键功能封装在以下jq过滤器中:
# Return an array of n items as if by
# [stream] | sort_by(filter) | .[-n:]
def maxn(stream; filter; n):
def maxn:
sort_by(filter) | .[-n :];
reduce stream as $x ([]; . + [$x] | maxn);
现在,只需另外三行即可获得手头问题(N==3)的解决方案:
maxn(inputs; .modified | strptime("%a %b %d %H:%M:%S +0000 %Y") | mktime; 3)
| group_by(.class_id)[]
| {(.[0].class_id): length}
请注意,这假定使用了-n命令行选项。如果省略,将忽略输入的第一行
大的
对于大型数据集,如果N的值也很大,则可能值得费心调整以上内容,以使用jq对二进制搜索(bsearch
)的支持,而不是sort\u by
。同样值得缓存mktime
值。非常感谢,它确实有效!有两件事需要澄清:(1)如何将其输出转换为CSV,即字面上的“A”,2\n“B”,1“
?(2)您能否分享一些易于阅读的关于Slurp开关的描述,解释为什么您的代码可以使用它(没有它就不能工作),以及更一般地,什么时候应该/不应该使用Slurp的经验法则?@wassrublef(1)使用[([0].class_id),length]|@csv
和-r
选项。(2)我想这超出了这里的范围,应该有它自己的问题……哇,内存方面确实是我的一个可能的问题,所以感谢您提供的替代解决方案——肯定也会尝试一下。