I'd like to perform vector math operations on a json array that stores numbers. In short how can we achieve one to one arithmetic operations by using jq?
I tried something with 'map' filter however could not achieved what I expect.
jq 'map(one-to-one)' <<< "{\"a\":[1,2], \"b\":[3,4]}"
or
jq 'map(one-to-one)' <<< "[[1,2],[3,4]]"
should produce
[3,8]
For this type of problem, it makes sense to define a generic function:
# Input is assumed to be an array of two numeric arrays of the same length
def pairwise: transpose | map(.[0] * .[1]);
We can now easily use this in a variety of ways:
[[1,2],[3,4]] | pairwise
{"a":[1,2], "b":[3,4]} | [.a,.b] | pairwise
{"a":[1,2], "b":[3,4]} | [.[]] | pairwise
The result in each of these cases is of course [3,8]
.
For very large inputs, it might be worthwhile avoiding transpose
:
def pairwise:
.[0] as $x | .[1] as $y
| reduce range(0; $x|length) as $i ([]; . + [$x[$i] * $y[$i]]);
Typically with vectors one is interested in the inner product, which for efficiency would best be defined directly, e.g. as follows:
def inner($a; $b):
reduce range(0;$a|length) as $i (0; . + $a[$i]*$b[$i]);