def window(values; $size; $step):
def checkparam(name; value): if (value | isnormal) and value > 0 and (value | floor) == value then . else error("window \(name) must be a positive integer") end;
checkparam("size"; $size)
| checkparam("step"; $step)
# We need to detect the end of the loop in order to produce the terminal partial group (if any).
# For that purpose, we introduce an artificial null sentinel, and wrap the input values into singleton arrays in order to distinguish them.
| foreach ((values | [.]), null) as $item (
{index: -1, items: [], ready: false};
(.index + 1) as $index
# Extract items that must be reused from the previous iteration
| if (.ready | not) then .items
elif $step >= $size or $item == null then []
else .items[-($size - $step):]
end
# Append the current item unless it must be skipped
| if ($index % $step) < $size then . + $item
else .
end
| {$index, items: ., ready: (length == $size or ($item == null and length > 0))};
if .ready then .items else empty end
);
def _nwise($n): window(.[]; $n; $n);
5条答案
按热度按时间j0pj023g1#
有一个(未记录的)内置
_nwise
满足功能要求:还有:
顺便说一下,
_nwise
既可以用于数组,也可以用于字符串。(我认为它是没有记录的,因为对一个合适的名称有一些疑问。)
TCO版本
不幸的是,内置版本的定义不小心,对于大型数组的性能不好。下面是一个优化的版本(它应该和非递归版本一样高效):
对于大小为300万的数组,这是相当高的性能:在旧Mac上为3.91s,最大驻留大小为162746368。
请注意,这个版本(使用尾部调用优化递归)实际上比本页其他地方显示的使用
foreach
的nwise/2
版本更快。z9smfwbn2#
以下
window/3
的面向流的定义是由Cédric Connes(github:connesc)提出的,它推广了_nwise
,并说明了一种“装箱技术”,它避免了使用流结束标记的需要,因此可以在流包含非JSON值nan
时使用。window/3
的第一个参数被解释为流。$size是窗口大小,$step指定要跳过的值的数目。例如,产量:
窗口/3和_nsize/1
来源:
https://gist.github.com/connesc/d6b87cbacae13d4fd58763724049da58
67up9zun3#
如果数组太大,内存中容纳不下,那么我将采用@CharlesDuffy建议的策略--也就是说,使用
nwise
的面向流的版本将数组元素流到jq的第二次调用中,例如:上述“驱动因素”为:
但请记住使用-n命令行选项。
从任意数组创建流:
因此,Shell管道可能如下所示:
对于使用
nwise/2
将300万个项的流分组为3个一组,对于jq的第二次调用,给出:
注意:此定义使用
nan
作为流结束标记。由于nan
不是JSON值,因此处理JSON流时不会出现问题。jum4pzuy4#
下面是黑客攻击,当然--但是 * 内存效率 * 黑客攻击,即使有一个任意长的列表:
管道的第一部分在输入JSON文件中流动,每个元素发出一行,假设数组由原子值组成(这里[]和{}是原子值)。因为它在流模式下运行,所以不需要在内存中存储整个内容,尽管它是一个文档。
管道的第二部分重复读取多达三个项目,并将它们组装成一个列表。
这样可以避免内存中一次需要三个以上的数据。
6uxekuva5#
有一个简单的方法对我很有效:
示例用法:
额外好处:它不使用递归,也不依赖于
_nwise
,所以它也可以使用jaq
。