Ech*_*lan 12 arrays shell json memory-efficient jq
我有一个包含数组的非常大的JSON文件.是否可以使用jq
将此数组拆分为几个固定大小的较小数组?假设我的输入是这样的:[1,2,3,4,5,6,7,8,9,10]
我想把它分成3个元素的长块.所需的输出jq
将是:
[1,2,3]
[4,5,6]
[7,8,9]
[10]
Run Code Online (Sandbox Code Playgroud)
实际上,我的输入数组有近300万个元素,都是UUID.
有一个(未记录的)内置,_nwise
满足功能要求:
$ jq -nc '[1,2,3,4,5,6,7,8,9,10] | _nwise(3)'
[1,2,3]
[4,5,6]
[7,8,9]
[10]
Run Code Online (Sandbox Code Playgroud)
也:
$ jq -nc '_nwise([1,2,3,4,5,6,7,8,9,10];3)'
[1,2,3]
[4,5,6]
[7,8,9]
[10]
Run Code Online (Sandbox Code Playgroud)
顺便提一下,_nwise
可以用于数组和字符串.
(我认为它没有记录,因为对某个名称有一些疑问.)
不幸的是,内置版本是粗心定义的,并且对大型数组不会很好.这是一个优化版本(它应该与非递归版本一样高效):
def nwise($n):
def _nwise:
if length <= $n then . else .[0:$n] , (.[$n:]|_nwise) end;
_nwise;
Run Code Online (Sandbox Code Playgroud)
对于一个300万的数组,这是非常高性能:旧Mac上为3.91s,最大驻留大小为162746368.
请注意,此版本(使用尾调用优化递归)实际上比本页其他地方显示的nwise/2
使用版本更快foreach
.
以下面向流的 定义window/3
,由 C\xc3\xa9dric Connes\n(github:connesc) 概括_nwise
,\n并说明了\n“装箱技术”,该技术避免了使用流结束标记的需要,因此如果流包含非 JSON 值,\n则可以使用nan
。还包括_nwise/1
关于的定义。window/3
的第一个参数window/3
被解释为流。$size 是窗口大小,$step 指定要跳过的值的数量。例如,
window(1,2,3; 2; 1)\n
Run Code Online (Sandbox Code Playgroud)\n\n产量:
\n\n[1,2]\n[2,3]\n
Run Code Online (Sandbox Code Playgroud)\n\ndef window(values; $size; $step):\n 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;\n checkparam("size"; $size)\n| checkparam("step"; $step)\n # We need to detect the end of the loop in order to produce the terminal partial group (if any).\n # For that purpose, we introduce an artificial null sentinel, and wrap the input values into singleton arrays in order to distinguish them.\n| foreach ((values | [.]), null) as $item (\n {index: -1, items: [], ready: false};\n (.index + 1) as $index\n # Extract items that must be reused from the previous iteration\n | if (.ready | not) then .items\n elif $step >= $size or $item == null then []\n else .items[-($size - $step):]\n end\n # Append the current item unless it must be skipped\n | if ($index % $step) < $size then . + $item\n else .\n end\n | {$index, items: ., ready: (length == $size or ($item == null and length > 0))};\n if .ready then .items else empty end\n );\n\ndef _nwise($n): window(.[]; $n; $n);\n
Run Code Online (Sandbox Code Playgroud)\n\nhttps://gist.github.com/connesc/d6b87cbacae13d4fd58763724049da58
\n