为什么 jq 列表构造函数和对象构造函数对生成器的行为不同?
Why jq list contructor and object constructor behaves differently for generators?
我想得到2个列表的笛卡尔积,尝试了以下方法:
echo [[1,2,3],[4,5,6]] | jq '[.[0][],.[1][]]'
我期望得到 [[1,4],[1,5],[1,6],[2,4],[2,5],....],但我真的得到的是 [1,2,3,4,5,6]
但是使用以下 2 个命令,我得到了笛卡尔积输出,
echo [[1,2,3],[4,5,6]] | jq '(.[0][] | tostring) + "," + (.[1][] | tostring)'
echo [[1,2,3],[4,5,6]] | jq '{"x": .[0][], "y": .[1][]}'
我的问题是:为什么逗号的行为与“+”不同?为什么列表构造函数的行为与对象构造函数不同?
因为那是 jq
中的 ,
operator 的工作原理。当两个过滤器被 ,
分隔时,相同的输入将被送入两者,输出值流将按顺序连接起来。在你的例子中,两个过滤器 return 分别在索引 0 和 1 对应的数组元素,结果被收集到一个数组中。
至于Object construction,手册上说的很清楚,
If one of the expressions produces multiple results, multiple dictionaries will be produced.
输入
{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
表达式
{user, title: .titles[]}
产生两个输出,一个对应数组中的每个值 titles
{"user":"stedolan", "title": "JQ Primer"}
{"user":"stedolan", "title": "More JQ"}
所以回到你最初的尝试,
- 在第一种情况下,每个表达式 运行 分别在原始输入数组上,结果只是组合在一起成为更大的
- 第三种情况属于创建对象的情况,其中一个表达式产生多个结果。由于您的两个表达式都会生成多个结果,因此您的结果字典形成为两个数组的笛卡尔积
- 第二种情况与3)几乎相似,但操作发生在字符串类型上,即在生成笛卡尔积之前,每个整数类型都转换为字符串。请注意,这产生的结果 既不是列表也不是字典
执行此操作时,您仍然可以在数组上生成笛卡尔积
.[0][] as $x | .[1][] as $y | [$x,$y]
如果将上面的过滤器放在 [..]
内,则将整个内容放入一个数组中 as
[.[0][] as $x | .[1][] as $y | [$x,$y]]
之所以有效,是因为 Variable binding operator 的语法为 expression as $variable
。
表达式 exp as $x | ...
表示表达式 exp
的每个值,运行 管道的其余部分具有整个原始输入,并且 $x
设置为价值。因此,作为 foreach
循环的功能。因此,对于我们的示例,对于 $x
中的每个值和 $y
中的每个值,我们形成结果 [$x, $y]
,这将是最终的笛卡尔积。
我想得到2个列表的笛卡尔积,尝试了以下方法:
echo [[1,2,3],[4,5,6]] | jq '[.[0][],.[1][]]'
我期望得到 [[1,4],[1,5],[1,6],[2,4],[2,5],....],但我真的得到的是 [1,2,3,4,5,6]
但是使用以下 2 个命令,我得到了笛卡尔积输出,
echo [[1,2,3],[4,5,6]] | jq '(.[0][] | tostring) + "," + (.[1][] | tostring)'
echo [[1,2,3],[4,5,6]] | jq '{"x": .[0][], "y": .[1][]}'
我的问题是:为什么逗号的行为与“+”不同?为什么列表构造函数的行为与对象构造函数不同?
因为那是 jq
中的 ,
operator 的工作原理。当两个过滤器被 ,
分隔时,相同的输入将被送入两者,输出值流将按顺序连接起来。在你的例子中,两个过滤器 return 分别在索引 0 和 1 对应的数组元素,结果被收集到一个数组中。
至于Object construction,手册上说的很清楚,
If one of the expressions produces multiple results, multiple dictionaries will be produced.
输入
{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
表达式
{user, title: .titles[]}
产生两个输出,一个对应数组中的每个值 titles
{"user":"stedolan", "title": "JQ Primer"}
{"user":"stedolan", "title": "More JQ"}
所以回到你最初的尝试,
- 在第一种情况下,每个表达式 运行 分别在原始输入数组上,结果只是组合在一起成为更大的
- 第三种情况属于创建对象的情况,其中一个表达式产生多个结果。由于您的两个表达式都会生成多个结果,因此您的结果字典形成为两个数组的笛卡尔积
- 第二种情况与3)几乎相似,但操作发生在字符串类型上,即在生成笛卡尔积之前,每个整数类型都转换为字符串。请注意,这产生的结果 既不是列表也不是字典
执行此操作时,您仍然可以在数组上生成笛卡尔积
.[0][] as $x | .[1][] as $y | [$x,$y]
如果将上面的过滤器放在 [..]
内,则将整个内容放入一个数组中 as
[.[0][] as $x | .[1][] as $y | [$x,$y]]
之所以有效,是因为 Variable binding operator 的语法为 expression as $variable
。
表达式 exp as $x | ...
表示表达式 exp
的每个值,运行 管道的其余部分具有整个原始输入,并且 $x
设置为价值。因此,作为 foreach
循环的功能。因此,对于我们的示例,对于 $x
中的每个值和 $y
中的每个值,我们形成结果 [$x, $y]
,这将是最终的笛卡尔积。