jq中的向量数学算术运算

时间:2019-09-13 07:17:07

标签: json math vector jq vector-multiplication

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

我尝试使用“地图”过滤器进行操作,但是无法达到我的期望。

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

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

应该产生

[3,8]

2 个答案:

答案 0 :(得分:1)

jq '. | transpose | map(reduce .[] as $item (1; . * $item))' <<< "[[1,2],[3,4]]"

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

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

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

答案 1 :(得分: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]);