Home > Software design >  how to use jq to get the gap value between array
how to use jq to get the gap value between array

Time:10-11

I had the following json array:

{
  "metric": {
    "instance": "100.120.207.215:8081",
    "job": "job1",
    "error_code": "500"
  },
  "values": [
    [
      1665129206,
      "128"
    ],
    [
      1665129236,
      "129"
    ],
    [
      1665129266,
      "130"
    ],
    [
      1665129296,
      "135"
    ]
  ]
}

I want to get the difference between each array, looks like

1665129236,1
1665129266,1
1665129296,5

Please help on it. Thanks a lot.

CodePudding user response:

If the arrays fit your memory, you can make two copies, shift them one apart to each other, transpose and subtract:

.values | [.[:-1], .[1:]] | transpose[]
| "\(.[1][0]),\(map(.[1] | tonumber) | .[1]-.[0])"

Demo

Alternatively, you can use either foreach or while to iterate over a window of two adjacent items:

.values | foreach .[1:][] as $v ([null, .[0]]; .[1:]   [$v];
  "\(.[1][0]),\(map(.[1] | tonumber) | .[1]-.[0])"
)

Demo

.values | while(has(1); .[1:])[:2]
| "\(.[1][0]),\(map(.[1] | tonumber) | .[1]-.[0])"

Demo

Output:

1665129236,1
1665129266,1
1665129296,5

CodePudding user response:

Building on pmf's excellent answer:

.values[][1] |= tonumber
| [.values[1:], .values[:-1]]
| transpose[]
| [
  first[0],
  (map(last) | first-last)
]
| join(",")

Since all your values are numbers, the final join filter could be replaced with @csv.

CodePudding user response:

Here's a solution that uses a generic derivative function that has already been used elsewhere on SO:

# Input: an array
# `delta` should be a non-negative integer, typically 1;
# p is the jq path expression to the quantity within an item, e.g. `.`
def derivative(delta; p):
  . as $in
  | [ range(delta; length) as $i
      | .[$i]
      | (p = ($in[$i] | p) - ($in[$i - delta] | p)) ];

.values |=
  (map(.[1] |= tonumber)
   | derivative( 1; .[1]))

  • Related