kizuna meraki
kizuna meraki

Reputation: 53

Comparing values between a previous element and its subsequent element in an array

I'm scrolling through the jq Manual and reading through every command available, but am only about 10% complete in reading it. (It's quite long, which is a good thing except that I have an art project presentation due in six days and I have to finish with this JSON analysis first so I can start measuring a cutting 350 meters of tape.)

I have a JSON file with exactly one object. That one object contains an array of 3555 JSON objects, which can be accessed via its index numbered from 0 to 3554. This shows the structure of one of those JSON objects (I've modified the phone numbers and the body/content of the instant message since this comes from a real conversation):

$ cat selected-convo.json | jq '.[3554]'

{
  "timestamp": 1589547750278,
  "attachments": [],
  "source": "+491604444444",
  "sourceUuid": "a258be99-b00a-456d-bba6-258d72878b64",
  "sourceDevice": 1,
  "sent_at": 1589536960941,
  "sent_to": [
    "+31707777777"
  ],
  "received_at": 1589547750278,
  "conversationId": "823c0416-9406-4922-8ee9-f3cf36c4784c",
  "type": "outgoing",
  "sent": true,
  "unidentifiedDeliveries": [
    "+31707777777"
  ],
  "expirationStartTimestamp": 1589536960941,
  "schemaVersion": 10,
  "id": "42e9ed93-ad1e-44fc-912a-dd310c16b52e",
  "body": "X xxxx X xxxx X xxx xxxxxxxxx xx xxx.",
  "contact": [],
  "decrypted_at": 1589547750368,
  "errors": [],
  "flags": 0,
  "hasAttachments": 0,
  "isViewOnce": false,
  "preview": [],
  "requiredProtocolVersion": 0,
  "supportedVersionAtReceive": 4,
  "quote": null,
  "sticker": null,
  "recipients": [
    "+31707777777"
  ]
}

I am only interested in measuring the time it took one person to respond to the other person. So, the key-value pairs I want are the sent at timestamp and whether the message is incoming or outgoing.

 $ cat selected-convo.json | jq '.[] | .sent_at, .type'

give me the following output (first ten in the array of 3555):

1577640636917
"outgoing"

1577674806478
"incoming"
1577674810527
"incoming"

1578513043504
"outgoing"
1578520666264
"outgoing"
1580600735958
"outgoing"
1580600816040
"outgoing"

1580601327790
"incoming"

1580602829082
"outgoing"
1580602833184
"outgoing"

BUT, I only want to see the first outgoing message followed by the first incoming message followed by the next outgoing message followed by the next incoming message, etc. (If I sent three messages in a row, I want do delete/ignore the second and third message and only look at the first one. If I received eight messages in a row before I responded, I want to only see the first of those messages and delete/skip/forward past the following seven. So from the list above, I want:

1577640636917
"outgoing"

1577674806478
"incoming"

1578513043504
"outgoing"

1580601327790
"incoming"

1580602829082
"outgoing"

Any ideas?

Upvotes: 1

Views: 595

Answers (1)

oguz ismail
oguz ismail

Reputation: 50775

I'd use foreach for that as the task basically requires a state machine that extracts some values from the current input whenever the state changes.

foreach .[] as {$type, $sent_at} (
  {};
  {prev: .curr, curr: $type};
  if .curr != .prev
  then $type, $sent_at
  else empty end
)

Upvotes: 2

Related Questions