I am trying to reduce an array
[
{"cat": "low", "value": "1"},
{"cat": "med", "value": "2"},
{"cat": "med", "value": "3"}
]
such that it produces this output:
{
"low": [
{
"cat": "low",
"value": "1"
}
],
"med": [
{
"cat": "med",
"value": "2"
},
{
"cat": "med",
"value": "3"
}
]
}
jq code
I tried this jq code:
reduce .[] as $curr ({};
$curr.cat as $category | # store the current category, eg "low"
.[$category] as $currArray | # store the current array that eg "low" points to
$currArray + [($curr)] as $newCategoryArray | # add the current object to the current array
. + {($category): ($newCategoryArray)} # use object addition to update the accumulator
)
Error
however I am getting the error
jq: error (at <stdin>:5): array ([{"cat":"me...) and object ({"low":[{"c...) cannot be added
exit status 5
Any help is appreciated.
jq snippet here: https://jqplay.org/s/HL0r2CqewAr
Notes:
If possible, could someone also explain why my reducer is throwing the error. I have simplified my problem so an explanation would help me greatly.
Removing an item from the input array, jq is able to run successfully.
The error is only encountered when the ‘category’ is not unique.

>Solution :
With reduce, add the items to and as an array:
jq 'reduce .[] as $curr ({}; .[$curr.cat] += [$curr])'
Alternatively, you can use group_by, then add the mapped items:
jq 'group_by(.cat) | map({(first.cat): .}) | add'
The same can be achieved using with_entries:
jq 'group_by(.cat) | with_entries(.key = .value[0].cat)'
Or even shorter, using INDEX:
jq 'group_by(.cat) | INDEX(first.cat)'
{
"low": [
{
"cat": "low",
"value": "1"
}
],
"med": [
{
"cat": "med",
"value": "2"
},
{
"cat": "med",
"value": "3"
}
]
}