Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQ: setdiff of two arrays

If I have an object with two arrays containing unique values in it

{"all":["A","B","C","ABC"],"some":["B","C"]}

How can I find .all - .some?

In this case I am looking for ["A","ABC"]

like image 806
Jon Avatar asked Apr 01 '15 16:04

Jon


3 Answers

@Jeff Mercado blew my mind! I didn't know array subtraction was allowed...

echo -n '{"all":["A","B","C","ABC"],"some":["B","C"]}' | jq '.all-.some'

yields

[
  "A",
  "ABC"
]
like image 151
Jon Avatar answered Nov 18 '22 00:11

Jon


I was looking for a similar solution but with the requirement that the arrays were being generated dynamically. Below solution just does the expected

array1=$(jq -e '')  // jq expression goes here
array2=$(jq -e '')  // jq expression goes here

array_diff=$(jq -n --argjson array1 "$array1" --argjson array2 "$array2" 
'{"all": $array1,"some":$array2} | .all-.some' )
like image 28
manikantan Avatar answered Nov 17 '22 23:11

manikantan


While - Array Subtraction is the best approach for this, here is another solution using del and indices:

. as $d | .all | del(.[ indices($d.some[])[] ])

It may be of help when you want to know which elements were removed. For example with the sample data and the -c (compact output) option, the following filter

  . as $d
| .all
| [indices($d.some[])[]] as $found
| del(.[ $found[] ])
| "all", $d.all, "some", $d.some, "removing indices", $found, "result", .

produces

"all"
["A","B","C","ABC"]
"some"
["B","C"]
"removing indices"
[1,2]
"result"
["A","ABC"]
like image 1
jq170727 Avatar answered Nov 18 '22 01:11

jq170727