Multiply arrays in JQ

Viewed 177

I have 2 arrays in 2 files and I'm trying to multiply them using JQ.

file1.json:

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

file2.json:

[
 {"x": "10", "y": "12", "z": "15"},
 {"x": "20", "y": "22", "z": "25"}
]

and the expected output:

[
 {"a": "1", "b": "2", "x": "10", "y": "12", "z": "15"},
 {"a": "1", "b": "2", "x": "20", "y": "22", "z": "25"},
 {"a": "3", "b": "4", "x": "10", "y": "12", "z": "15"},
 {"a": "3", "b": "4", "x": "20", "y": "22", "z": "25"}
]

When I do jq .[0] * .[1] file1.json file2.json it says

array ... and array ... can't be multiplied

2 Answers
jq -c ".[]" file1.json  > f1.jl
jq -c ".[]" file2.json  > f2.jl
while read a; do while read b; do echo $a $b | jq -s 'add' -c ; done < f2.jl  ; done < f1.jl | jq -s 

You haven't been very clear on what you intend. I infer that you're looking for a cartesian product of the input arrays, such that your output array has an object for each possible pairing of one object from file1's array and one object from file2's array, and that the output objects are the merging of the two paired input objects.

Any time you combine two expressions that output multiple items in an object constructor or a binary operation you will get a cartesian product. Since the + operator merges together objects, it's a good candidate.

This should do what you want:

jq -n --slurpfile file1 file1.json --slurpfile file2 file2.json '[$file2[0][] + $file1[0][]|{a,b,x,y,z}]'

We need the first [0] to "unwrap" the extra array that --slurpfile introduces. The following [] iterates over all the objects in your input array. Since both subexpressions to the + operator produce multiple items, we get the desired cartesian product. Lastly the {a,b,x,y,z} is used to put the output fields in the order you desire - it's largely cosmetic and you can omit it if you don't care.

Related