为什么“减少”不减少jq

时间:2019-08-18 23:44:16

标签: jq

tl; dr

jq的语言,为什么

$ jq --compact-output reduce (1,2,3,4) as $i ([]; . + [$i])
[1,2,3,4]

不同
$ jq --compact-output (1,2,3,4) | reduce . as $i ([]; . + [$i])
[1]
[2]
[3]
[4]

完整的问题和讨论

我有一个理论上的问题,我想出了一种方法来获得想要的转换,但是我仍然不完全理解为什么我的第一次尝试失败了,我想解释一下。

jqPlay上的互动示例

我有输入

{
  "data": {
    "k1": "v1"
  },
  "item": {
    "data": {
      "k2": "v2"
    }
  }, 
  "list": {
    "item": {
      "data": {
        "k3": "v3",
        "k4": "v4"
      }
    }
  }
}

,我想将作为“数据”键的直接子级的所有键的所有值收集到一个数组中。所以我想要的输出是

["v1","v2","v3","v4"]

我最终发现这可行

jq --compact-output '[.. | .data? | select(.) | to_entries | .[].value]'

我的问题是,为什么我不能使它与reduce一起使用?我最初尝试过

.. | .data? | select(.) | to_entries | .[].value | reduce . as $v ([]; . + [$v])

但这给了我

["v1"]
["v2"]
["v3"]
["v4"]

相反。我的问题是为什么? reduce应该迭代多个值,但是它会迭代哪种类型的多个值,以及哪种类型的值被视为单独的reduce语句的单独输入?

我想我的基本困惑是.(点)何时是具有4个结果的表达式,什么时候是4个表达式?或者,如果.始终是一个带有1个结果的表达式,那么如何将4个结果收集回1,这就是reduce的全部含义?数组运算符是唯一的方法吗?

1 个答案:

答案 0 :(得分:2)

以下形式的表达式:

reduce STREAM as ...

减少给定的流,而复合表达式:

STREAM | reduce . as ...

为流中的每个项目调用一次reduce,对于每次调用,.就是那个项目。


如果在这种情况下不清楚流的概念,那么您可能有兴趣阅读我写的面向流的jq简介: https://github.com/pkoppstein/jq/wiki/A-Stream-oriented-Introduction-to-jq