fmic_
fmic_

Reputation: 2436

restructure JSON file with jq: regroup values in an array

I'm new to jq and I can't quite figure out how to transform a JSON file formatted like this:

[
  {
    "name": "person 1",
    "code": "AAA",
    "latitude": 11,
    "longitude": 22 
  },
  {
    "name": "person 2",
    "code": "AAA",
    "latitude": 11,
    "longitude": 22 
  },
  {
    "name": "person 3",
    "code": "BBB",
    "latitude": 33,
    "longitude": 44 
  },
  {
    "name": "person 4",
    "code": "BBB",
    "latitude": 33,
    "longitude": 44 
  }
]

into this:

[
  {
   "code": "AAA",
   "latitude": 11,
   "longitude": 22,
   "people": ["person 1", "person 2"]
  },
  {
   "code": "BBB",
   "latitude": 33,
   "longitude": 44,
   "people": ["person 3", "person 4"]
  }
]

I figured out how to use map() and unique to get the unique combinations of code, latitude, longitude but not how to add the names into an array.

Upvotes: 1

Views: 336

Answers (2)

peak
peak

Reputation: 116680

Here's a simple solution using group_by:

group_by(.code)
| map( reduce .[] as $x (.[0] | del(.name); 
         .people += [$x.name]) )

Upvotes: 1

peak
peak

Reputation: 116680

Here's a solution that is more efficient than one using group_by in that the latter involves a sort.

Efficiency can be achieved using the builtin INDEX/1, and the generic function aggregate_by defined as:

def aggregate_by(s; f; g):
  reduce s as $x  (null; .[$x|f] += [$x|g]);

aggregate_by(.[]; .code; .name) as $dict
| INDEX(.code)
| [.[]]
| map(del(.name) | .person = $dict[.code])

Upvotes: 1

Related Questions