I think this question indicates that I don't quite get how jq works. Given this data:
$ DATA='{ "postgresServer":["d"], "playServer":["c"], "ignore":["b"], "generic":["a"] }'
I want to add a new item to the ignore array:
$ echo "$DATA" | jq ".ignore += [\"b\"]"
{
"generic": [
"a"
],
"ignore": [
"b",
"b"
],
"playServer": [
"c"
],
"postgresServer": [
"d"
]
}
This gives me a duplicate item. I can use unique to eliminate the duplicate:
$ echo "$DATA" | jq ".ignore += [\"b\"] | .ignore | unique"
[
"b"
]
But I can't figure out how to give me the desired result:
{
"generic": [
"a"
],
"ignore": [
"b"
],
"playServer": [
"c"
],
"postgresServer": [
"d"
]
}
I read a comment that suggested that add was the function to use, but I could not make it work.
I'm thinking it'd be nice to have a primitive for adding an element to an
array IFF it's not already there. Clearly one can program around the lack
of such a primitive, but it's going to be faster in C, and easier to use.
Ditto for adding/modifying a property to an object, and even a property
in an item/object in an array. Currently the expression for selecting
the array item and then adding/modifying a specific property is a bit scary.
You can write it using the |= operation, which modifies a field using an arbitrary bit of jq code:
.ignore |= (. + ["b"] | unique)
. + ["b"] adds "b" to the end of the array, and unique removes duplicates. If this is something you expect to do a lot, you can write a function for it:
def set_insert(value): (. + [value] | unique); .ignore |= set_insert("b")
I know it's old but thought I'd share my opinion (sorry...)
I appreciate the guidance here, but it would be really nice if jq was similar to other known languages with an append() or push() primitive, though I will look into creating a definition to do this in my own code.
@notjames: push, pop, append, prepend, these are easy operations in jq:
def push($item): . + [$item]; # it's much cheaper to append than prepend, so push on the right
def pop: .[0:-1];
def append($item): . + [$item]; # same as push
def prepend($item): [$item] + .;
An efficient array-based implementation of sets, however, might best be done in C. Also, the append operation would be significantly more efficient in C, for the pop operation as implemented above wouldn't be.
Most helpful comment
You can write it using the
|=operation, which modifies a field using an arbitrary bit of jq code:. + ["b"]adds"b"to the end of the array, anduniqueremoves duplicates. If this is something you expect to do a lot, you can write a function for it: