JdeHaan
JdeHaan

Reputation: 392

JQ how to merge multiple objects in an array into one (2)

A little more sophisticated as my previous question. Missing indexes mess things up too.

Input:

{
  "a": [
    { "b": 1, "d": "p" },

    { "b": 3, "d": "r" },
    { "b": 4, "d": "s" }
  ],
  "h": [
    { "b": 1, "i": "k" },
    { "b": 2, "i": "l" },

    { "b": 4, "i": "n" }
  ]
}

Desired output:

{
  "q": [
    { "b": 1, "d": "p", "i": "k" },
    { "b": 2, "i": "l" },
    { "b": 3, "d": "r" },
    { "b": 4, "d": "s", "i": "n" }
  ]
}

Tried:

jq '[.a, .h ] | transpose | map(add)| {l: .}'
jq '[ .a[] , .h[] ] | unique_by(.b) | { l: sort_by(.b) }'
jq '[ .a[] + .h[] ] | unique_by(.b) | { l: sort_by(.b) }'
jq '[ .a[] * .h[] ] | unique_by(.b) | { l: sort_by(.b) }'

Upvotes: 1

Views: 3117

Answers (2)

peak
peak

Reputation: 116740

Here's a solution using the generic function aggregate_by, defined as follows:

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

First, notice that with this def:

aggregate_by(.a[], .h[]; .b|tostring; .)[]
| add

produces the desired array except for the ordering of elements. If the ordering of elements in the output array is unimportant, then the above could be tweaked to provide a simple solution that does not involve group_by, which entails sorting.

To produce the desired (sorted-by-b) output, we could tweak the above as follows:

{q: [aggregate_by(.a[], .h[]; .b|tostring; .)[]]
    | map(add)
    | sort_by(.b) }

Upvotes: 1

oguz ismail
oguz ismail

Reputation: 50750

Use group_by to group array elements by a filter's output (.b in this case):

jq '{ q : [ add | group_by(.b)[] | add ] }' file

Upvotes: 2

Related Questions