Home > OS >  jq reverse data structure and append to array
jq reverse data structure and append to array

Time:01-29

I have:

[
  {
    "name": "Trevor",
    "fruits": ["apple", "banana"]
  }, {
    "name": "Lily",
    "fruits": ["apple", "haribo"]
  }
]

And I want a jq filter to kind of reverse the data structure, and get the names in an array:

[
  {
    "fruit": "apple",
    "liked_by": ["Trevor", "Lily"]
  }, {
    "fruit": "banana",
    "liked_by": ["Trevor"]
  }, {
    "fruit": "haribo",
    "liked_by": ["Lily"]
  }
]

I am trying things like this:

jq '
  [
    .[]
    | .name as $name
    | .fruits[]
    | {"name": $name, "liked_by":  = [.]}
  ]
' input.json

CodePudding user response:

One way would be using group_by with some maps to bring the parts in place:

map(.fruit = .fruits[]) | group_by(.fruit)
| map({fruit: first.fruit, liked_by: map(.name)})

Demo


Another way would be creating an index (dictionary) using nested reduces, then mapping the result back to an array:

reduce .[] as {$name, $fruits} ({}; reduce $fruits[] as $fruit (.;
  .[$fruit] |= (.fruit = $fruit | .liked_by  = [$name])
)) | map(.)

Demo


Output:

[
  {
    "fruit": "apple",
    "liked_by": [
      "Trevor",
      "Lily"
    ]
  },
  {
    "fruit": "banana",
    "liked_by": [
      "Trevor"
    ]
  },
  {
    "fruit": "haribo",
    "liked_by": [
      "Lily"
    ]
  }
]
  • Related