【问题标题】:Vector math arithmetic operations in jqjq中的向量数学算术运算
【发布时间】:2019-09-13 07:17:07
【问题描述】:

我想对存储数字的 json 数组执行向量数学运算。简而言之,我们如何使用 jq 实现一对一的算术运算?

我尝试了一些使用“地图”过滤器的方法,但未能达到我的预期。

jq 'map(one-to-one)' <<< "{\"a\":[1,2], \"b\":[3,4]}"

jq 'map(one-to-one)' <<< "[[1,2],[3,4]]"

应该产生

[3,8]

【问题讨论】:

    标签: json math vector jq vector-multiplication


    【解决方案1】:

    对于这类问题,定义一个泛型函数是有意义的:

    # Input is assumed to be an array of two numeric arrays of the same length
    def pairwise: transpose | map(.[0] * .[1]);
    

    我们现在可以通过多种方式轻松使用它:

    [[1,2],[3,4]] | pairwise
    
    {"a":[1,2], "b":[3,4]} | [.a,.b] | pairwise
    
    {"a":[1,2], "b":[3,4]} | [.[]] | pairwise
    

    每种情况下的结果当然是[3,8]

    效率

    对于非常大的输入,可能值得避免使用transpose

    def pairwise:
       .[0] as $x | .[1] as $y 
       | reduce range(0; $x|length) as $i ([]; . + [$x[$i] * $y[$i]]);
    

    通常对于向量,人们对内积感兴趣,为了提高效率,最好直接定义它,例如如下:

    def inner($a; $b):
      reduce range(0;$a|length) as $i (0; . + $a[$i]*$b[$i]);
    

    【讨论】:

    • 我什至不考虑计算时间意义上的转置。感谢您的考虑并提出替代方法。
    【解决方案2】:
    jq '. | transpose | map(reduce .[] as $item (1; . * $item))' <<< "[[1,2],[3,4]]"
    

    Transpose 为我们提供了需要相乘的元素:[[1, 3], [2, 4]]。然后我们可以使用reduce将每个子数组映射到它的乘积。

    对象版本有点不同,因为我们需要从属性中获取这些值:

    jq '[.[]] | transpose | map(reduce .[] as $item (1; . * $item))' <<< "{\"a\":[1,2], \"b\":[3,4]}"
    

    【讨论】:

    • 谢谢阿马丹,尤其是你更新的答案解决了我的问题。
    猜你喜欢
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 2020-05-01
    • 2019-02-01
    相关资源
    最近更新 更多