2

Given

[{
  "objects": [{
    "key": "value"
  },{
    "key": "value"
  }]
}, {
  "objects": [{
    "key": "value"
  }, {
    "key": "value"
  }]
}]

How do I generate

[{
  "objects": [{
    "id": 0,
    "key": "value"
  },{
    "id": 1,
    "key": "value"
  }]
}, {
  "objects": [{
    "id": 2,
    "key": "value"
  }, {
    "id": 3,
    "key": "value"
  }]
}]

Using jq?

I tried to use this one, but ids are all 0:

jq '[(-1) as $i | .[] | {objects: [.objects[] | {id: ($i + 1 as $i | $i), key}]}]'
peak
  • 105,803
  • 17
  • 152
  • 177
hgl
  • 2,034
  • 4
  • 21
  • 30

2 Answers2

1

The key to a simple solution here is to break the problem down into easy pieces. This can be accomplished by defining a helper function, addId/1. Once that is done, the rest is straightforward:

# starting at start, add {id: ID} to each object in the input array 
def addId(start):
  reduce .[] as $o
    ([];
     length as $l 
     | .[length] = ($o | (.id = start + $l)));

reduce .[] as $o
  ( {start: -1, answer: []};
    (.start + 1) as $next
    | .answer += [$o | (.objects |= addId($next))]
    | .start += ($o.objects | length) )
| .answer
peak
  • 105,803
  • 17
  • 152
  • 177
  • Thank you, it works! And inspired by your solution, I came up with a slightly different one. Added as another answer, but I will accept your answer. – hgl Mar 10 '17 at 07:13
  • Thanks, @hgl. I didn't use foreach as it requires jq 1.5 or later, whereas `reduce` was an early bird. – peak Mar 10 '17 at 07:34
0

Inspired by @peak answer, I came up with this solution. Not much difference, just shorter way to generate IDs and opt for foreach instead of reduce since there is intermediate result involved.

def addIdsStartWith($start):
    [to_entries | map((.value.id = .key + $start) | .value)];

[foreach .[] as $set (
    {start: 0};
    .set = $set |
        .start as $start | .set.objects |= addIdsStartWith($start) |
        .start += ($set.objects | length);
    .set
)]
hgl
  • 2,034
  • 4
  • 21
  • 30