Using jq, I want to assign an incrementing number num
to each element in the order they appear in the input, but keep the same number for elements that share a ref
value with other elements.
So considering this input,
[
{"ref": "e13bb9", "name": "One"},
{"ref": "11b8cc", "name": "Two"},
{"ref": "e13bb9", "name": "Three"}
]
I would want the following output:
[
{"ref": "e13bb9", "name": "One", "num": 0},
{"ref": "11b8cc", "name": "Two", "num": 1},
{"ref": "e13bb9", "name": "Three", "num": 0}
]
In other words, the element with "name" == "One"
should have "num": 0
(since it is the first element), then the element with "name" == "Two"
should have "num": 1
(since it is the second element, and its ref
value has not occurred before), then the element with "name" == "Three"
should again have "num": 0
(since it has the same ref
as the element with "name" == "One"
, and should thus share its num
).
I tried to use group_by(.ref)
to group the elements with the same ref
together, but that does not preserve the order in which they occur in the input; in other words, "name" == "Two"
came before "name" == "One"
and "name" == "Three"
.
Keep a lookup table for the .ref
values, and determine the next value by its size (length
):
reduce .[] as $i ({};
.num |= (.[$i.ref] //= length) | .arr += [$i + {num: .num[$i.ref]}]
) | .arr
[
{
"ref": "e13bb9",
"name": "One",
"num": 0
},
{
"ref": "11b8cc",
"name": "Two",
"num": 1
},
{
"ref": "e13bb9",
"name": "Three",
"num": 0
}
]