phear
phear

Reputation: 55

How to merge (average/sum) duplicated objects in .json via jq?

I'm trying to get rid of duplicates that sometimes appear in my input.
Here is sample of data:

{
  "some": "very",
  "random": 0.228,
  "stuff": 31337,
  "people": [
    {
      "name": "carl",
      "height": "180cm",
      "wifes": 1,
      "sons": 0
    },
    {
      "name": "charlie",
      "height": "166cm",
      "wifes": 0,
      "sons": 2
    },
    {
      "name": "carl",
      "height": "180cm",
      "wifes": 1,
      "sons": 1
    },
    {
      "name": "carl",
      "height": "195cm",
      "wifes": 1.95,
      "sons": 12
    }
  ]
}

There is bunch of carl's, but only 2 of them are duplicates - name:carl & height:180cm.
For example I need to average amount of his wifes and sum his sons.
Here is expected result:

[
  {
    "name": "carl",
    "height": "180cm",
    "wifes": 1,
    "sons": 3
  },
  {
    "name": "charlie",
    "height": "166cm",
    "wifes": 0,
    "sons": 2
  },
  {
    "name": "carl",
    "height": "195cm",
    "wifes": 1.95,
    "sons": 12
  }
]

I tried using 'add' and 'reduce' but I'm pretty newb in jq ><

Upvotes: 3

Views: 332

Answers (1)

peak
peak

Reputation: 116910

The grouping can be achieved by group_by/1 using [.name,.height] as the grouping criterion:

def sum(f): map(f) | add;

def average(f): sum(f) / length;

def consolidate:
  .[0]
  + {wifes: average(.wifes)}
  + {sons:  sum(.sons) } ;

.people
| group_by([.name,.height])
| map(consolidate)

Output

The output is as per the given descriptive requirements:

[
  {
    "name": "carl",
    "height": "180cm",
    "wifes": 1,
    "sons": 1
  },
  {
    "name": "carl",
    "height": "195cm",
    "wifes": 1.95,
    "sons": 12
  },
  {
    "name": "charlie",
    "height": "166cm",
    "wifes": 0,
    "sons": 2
  }
]

Upvotes: 3

Related Questions