skip to Main Content

I have an input like below which just has stageIds, along with their submit and completion time in unix time seconds

[
  {
    "stageId": 1,
    "submitTime_epoch_secs": 5,
    "completionTime_epoch_secs": 10
  },
  {
    "stageId": 2,
    "submitTime_epoch_secs": 15,
    "completionTime_epoch_secs": 17
  },
  {
    "stageId": 3,
    "submitTime_epoch_secs": 29,
    "completionTime_epoch_secs": 30
  }
]

desired output is below, where each stageId, submit, and completion times are compared with previous and next and the delay is added as another key/val per element.

[
  {
    "stageId": 1,
    "submitTime_epoch_secs": 5,
    "completionTime_epoch_secs": 10,
    "delayTillNextStageSubmit",5
    "delayFromPrevStageComplete",null
  },
  {
    "stageId": 2,
    "submitTime_epoch_secs": 15,
    "completionTime_epoch_secs": 17,
    "delayTillNextStageSubmit",12
    "delayFromPrevStageComplete",5
  },
  {
    "stageId": 3,
    "submitTime_epoch_secs": 29,
    "completionTime_epoch_secs": 30,
    "delayTillNextStageSubmit",null
    "delayFromPrevStageComplete",12
  }
]

here the stageId 1 delayTillNextStageSubmit is difference between stageId 2 submitTime and stageId 1 completion time, 15 – 10 = 5.

is this possible with jq?

I am new to jq, so don’t know how to solve this

2

Answers


  1. Here is a derivative method for this kind of task:

    # Input: an array
    # $delta is the lag (e.g. 1) or lead (e.g. -1)
    # p1 is the jq path expression to the quantity within "this" item
    # p2 is the jq path expression to the quantity within "that" item
    # q  is the jq path expression for the delta value
    def derivative($delta; p1; p2; q):
        . as $in
        | length as $length
        | [ range(0; $length) as $i
            | .[$i]
            | if 0 <= $i and $i < $length and 0 <= ($i - $delta) and ($i - $delta) < $length
              then q = ($in[$i] | p1) - ($in[$i - $delta] | p2) 
              | q |= (if $delta > 0 then . else - . end)
              else q = null
              end ];
    

    If $data holds your data, then based on my understanding of the question, you would invoke it like this:

    $data
    | derivative(-1; .completionTime_epoch_secs; .submitTime_epoch_secs; .delayTillNextStageSubmit)
    | derivative( 1; .submitTime_epoch_secs; .completionTime_epoch_secs; .delayFromPrevStageComplete)
    

    Please note there seems to be an inconsistency between the input and output for stageId 3 in your example: "submitTime_epoch_secs" is shown as 22 and then as 29.

    Login or Signup to reply.
  2. . as $array | to_entries | map(
        .value.delayFromPrevStageComplete = .value.submitTime_epoch_secs - $array[.key - 1].completionTime_epoch_secs |
        .value.delayTillNextStageSubmit = $array[(.key + 1) % length].submitTime_epoch_secs - .value.completionTime_epoch_secs |
        .value
    ) | (
        .[0].delayFromPrevStageComplete,
        .[-1].delayTillNextStageSubmit
    ) = null
    

    to_entries is used to get the index of each entry as .key.
    (.key + 1) % length is used to avoid an error with the last element.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search