【问题标题】:Why jq list contructor and object constructor behaves differently for generators?为什么 jq 列表构造函数和对象构造函数对于生成器的行为不同?
【发布时间】:2021-12-06 22:01:32
【问题描述】:

我想得到 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 cartesian-product


    【解决方案1】:

    因为这就是jq 中的, operator 的工作原理。当两个过滤器由, 分隔时,相同的输入将被馈送到两者,输出值流将按顺序连接。在您的情况下,两个过滤器分别在索引 0 和 1 处返回相应的数组元素,并将结果收集到一个数组中。

    至于Object construction,说明书上说得很清楚,

    如果其中一个表达式产生多个结果,则会产生多个字典。

    在输入时

    {"user":"stedolan","titles":["JQ Primer", "More JQ"]}
    

    表达式

    {user, title: .titles[]}
    

    产生两个输出,一个用于数组titles中的每个值

    {"user":"stedolan", "title": "JQ Primer"}
    {"user":"stedolan", "title": "More JQ"}
    

    所以回到你最初的尝试,

    1. 在第一种情况下,每个表达式分别在原始输入数组上运行,结果只是组合在一起成为更大的一个
    2. 第三种情况属于创建对象的情况,即其中一个表达式产生多个结果。由于您的两个表达式都生成多个结果,因此您的结果字典形成为两个数组的笛卡尔积
    3. 第二种情况与 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 的每个值,使用整个原始输入运行管道的其余部分,并将@​​987654337@ 设置为该值。因此,作为foreach 循环的功能。因此,在我们的示例中,对于$x 中的每个值和$y 中的每个值,我们形成结果[$x, $y],这将是得到的笛卡尔积。

    【讨论】:

    • 非常感谢这么详细的解释。真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2018-03-05
    • 2020-03-06
    • 1970-01-01
    • 2018-01-29
    • 2020-09-16
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    相关资源
    最近更新 更多