Home > database >  jq to report rolling differences between array element values
jq to report rolling differences between array element values

Time:01-29

I have a 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": 22,
    "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

CodePudding user response:

Here is one way:

reduce range(length - 1) as $i (.;
  .[$i].delayTillNextStageSubmit = .[$i   1].submitTime_epoch_secs - .[$i].completionTime_epoch_secs
) |
reduce range(1; length) as $i (.;
  .[$i].delayFromPrevStageComplete = .[$i - 1].delayTillNextStageSubmit
)

Online demo

CodePudding user response:

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.

  • Related