通过在jq中一对一比较两个流进行过滤



我有流

{
"key": "a",
"value": 1
}
{
"key": "b",
"value": 1
}
{
"key": "c",
"value": 1
}
{
"key": "d",
"value": 1
}
{
"key": "e",
"value": 1
}

(true,true,false,false,true)

我想一对一地比较这两个,并且仅当对应的布尔值为true时才打印对象。

所以我想输出

{
"key": "a",
"value": 1
}
{
"key": "b",
"value": 1
}
{
"key": "e",
"value": 1
}

我试过了(https://jqplay.org/s/GGTHEfQ9s3)

filter:
. as $input | foreach (true,true,false,false,true) as $dict ($input; select($dict))
input:
{
"key": "a",
"value": 1
}
{
"key": "b",
"value": 1
}
{
"key": "c",
"value": 1
}
{
"key": "d",
"value": 1
}
{
"key": "e",
"value": 1
}

但我得到了输出:

{"key":"a","value":1}
{"key":"a","value":1}
null
{"key":"b","value":1}
{"key":"b","value":1}
null
{"key":"c","value":1}
{"key":"c","value":1}
null
{"key":"d","value":1}
{"key":"d","value":1}
null
{"key":"e","value":1}
{"key":"e","value":1}
null

我们将不胜感激。

一种方法是以数组的形式读取流,使用transpose来匹配它们的项,并使用select一个来输出另一个:

jq -s '[.,[(true,true,false,false,true)]] | transpose[] | select(.[1])[0]' objects.json

演示

另一种方法是将流作为数组读取,将布尔值数组转换为条件匹配的indices,并使用它们引用到对象数组中:

jq -s '.[[(true,true,false,false,true)] | indices(true)[]]' objects.json

演示

相同的方法,但使用nth引用到inputs流中需要更多的预防措施,因为流输入的连续消耗需要提供到nth的相对距离,而不是绝对位置。可以通过使用indexwhile循环依次检查下一个true值的位置来实现转换:

jq -n 'nth([true,true,false,false,true] | while(. != []; .[index(true) + 1:]) | index(true) | values; inputs)' objects.json

演示

也可以使用reduce直接迭代布尔值,只使用select任何适当的input:

jq -n 'reduce (true,true,false,false,true) as $dict ([]; . + [input | select($dict)]) | .[]' objects.json

演示

使用foreach的解决方案,就像您想要的那样,也需要-n选项来避免错过第一项:

jq -n 'foreach (true,true,false,false,true) as $dict (null; input | select($dict))' objects.json

演示

不幸的是,jq的每次调用目前最多只能处理一个外部JSON流。这通常不是一个问题,除非两个流都很大,所以在这个答案中,我将重点关注一个可扩展的解决方案。事实上,无论数据流有多大,所需的计算机内存量都是微不足道的

为了简单起见,我们假设:

  • demon.json是一个由json布尔值流组成的文件(即,不以逗号分隔(
  • object.json是json对象流
  • 流具有相同的长度
  • 我们在bash或类似bash的环境中工作

然后我们可以使用:

paste -d 't' demon.json <(jq -c . objects.json) | jq -n '
foreach inputs as $boolean (null; input; select($boolean))'

因此,除了pastejq的启动成本外,我们基本上只需要足够的内存来一次保存objects.json中的一个对象。这个解决方案也很快。

当然,如果objects.json已经是JSONL(json行(格式,那么就不需要对上面的jq进行第一次调用。

最新更新