Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Have jq return the index number of an element in an array

Tags:

json

jq

I want jq to return the index of an alement in an array based on a search.

Using the below array I call jq to find the value "FooBar" of a key "text":

jq '.arr[] | .[3].text | tostring | select(contains("FooBar") )' < file.json

The result is:

"FooBar"

But what I actually want is the index of the most outer array "arr" that this text:FooBar pair is nested in, which is 0 in this case.

Can this e achieved in jq?

{
"arr": [
    [
      "create",
      "w71",
      "rwt.widgets.Label",
      {
        "parent": "w68",
        "style": "1",
        "bounds": "2",
        "tabIndex": -1,
        "background": "ww",
        "font": "test",
        "text": "FooBar",
        "alignment": "right"
      }
    ],
    [
          "create",
          "w72",
          "rwt.widgets.Label",
          {
            "parent": "w68",
            "style": "22",
            "bounds": "1",
            "tabIndex": -1,
            "foreground": "null",
            "background": "1",
            "font": "2",
            "text": "55",
            "alignment": "right"
          }
        ]
  ]
}
like image 356
tzippy Avatar asked Mar 04 '23 19:03

tzippy


2 Answers

You can first convert the elements in the array to entries, this way both the key and the value are present in the output:

jq '.arr | to_entries'

Give the result where the key is present in the output:

[
  {
    "key": 0,
    "value": [
      "create",
      "w71",
      "rwt.widgets.Label",
      {
        "parent": "w68",
        "style": "1",
        "bounds": "2",
        "tabIndex": -1,
        "background": "ww",
        "font": "test",
        "text": "FooBar",
        "alignment": "right"
      }
    ]
  },
  {
    "key": 1,
    "value": [
      "create",
      "w72",
      "rwt.widgets.Label",
      {
        "parent": "w68",
        "style": "22",
        "bounds": "1",
        "tabIndex": -1,
        "foreground": "null",
        "background": "1",
        "font": "2",
        "text": "55",
        "alignment": "right"
      }
    ]
  }
]

Performing your filtering and returning the index then becomes fairly trivial:

jq '.arr | to_entries | .[] | select(.value[3].text | contains("FooBar")) | .key' <test.json
like image 99
Stuart Wakefield Avatar answered Mar 24 '23 08:03

Stuart Wakefield


Here's a solution that does not depend on the assumption that the object of interest has a fixed position within the array:

.arr
| map( .[] | objects | .text ) 
| index("FooBar")

More robustly:

.arr 
| map( first(.[] | objects) // null | .text )
| index("FooBar")
like image 33
peak Avatar answered Mar 24 '23 06:03

peak