Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to group array entries by key and by key value in jq?

Given this json:

{
  "hits": [
    {
      "country": "PT",
      "level": "H2",
      "id": "id1"
    },
    {
      "country": "PT",
      "level": "H1",
      "id": "id2"
    },
    {
      "country": "CZ",
      "level": "H2",
      "id": "id3"
    },
    {
      "country": "IT",
      "level": "H2",
      "id": "id4"
    },
    {
      "country": "PT",
      "level": "H3",
      "id": "id5"
    },
    {
      "country": "PT",
      "level": "H3",
      "id": "id6"
    },
    {
      "country": "PT",
      "level": "H4”,
      "id": "id7"
    }
  ]
}

I would like to group this by country and in two levels, one having the H1 and H2 entries, and the other having the H3 and H4 entries. Furthermore, I would like that ids and levels to be encapsulated in an object called "entities" like follows:

{
  "hits": [
    {
      "country": "PT",
      "entities": [
        {
          "id": "id2",
          "level": "H1"
        },
        {
          "id": "id1",
          "level": "H2"
        }
      ]
    },
    {
      "country": "CZ",
      "entities": [
        {
          "id": "id3",
          "level": "H2"
        }
      ]
    },
    {
      "country": "IT",
      "entities": [
        {
          "id": "id4",
          "level": "H2"
        }
      ]
    },
    {
      "country": "PT",
      "entities": [
        {
          "id": "id5",
          "level": "H3"
        },
        {
          "id": "id6",
          "level": "H3"
        },
        {
          "id": "id7",
          "level": "H4"
        },
      ]
    }
  ]
}

I am quite new to jq. Could anyone help me doing this in jq?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Provide group_by with two criteria: one is simply the value of .country, the other is the containedness of .level in a given set of values (here, using IN with H1 and H2, which evaluates to a boolean). After the grouping, use a map to rectify the shapes of the individual groups as desired.

.hits |= (
  group_by(.country, IN(.level; "H1", "H2")) 
  | map((first | {country}) + {entities: map({id, level})})
)
{
  "hits": [
    {
      "country": "CZ",
      "entities": [
        {
          "id": "id3",
          "level": "H2"
        }
      ]
    },
    {
      "country": "IT",
      "entities": [
        {
          "id": "id4",
          "level": "H2"
        }
      ]
    },
    {
      "country": "PT",
      "entities": [
        {
          "id": "id5",
          "level": "H3"
        },
        {
          "id": "id6",
          "level": "H3"
        },
        {
          "id": "id7",
          "level": "H4"
        }
      ]
    },
    {
      "country": "PT",
      "entities": [
        {
          "id": "id1",
          "level": "H2"
        },
        {
          "id": "id2",
          "level": "H1"
        }
      ]
    }
  ]
}

Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading