реструктурировать файл JSON с помощью значений jq: regroup в массиве - PullRequest
1 голос
/ 06 марта 2019

Я новичок в jq и не могу понять, как преобразовать файл JSON, отформатированный так:

[
  {
    "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 
  }
]

в это:

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

Я понялузнать, как использовать map() и unique, чтобы получить уникальные комбинации code, latitude, longitude, но не как добавлять имена в массив.

Ответы [ 3 ]

1 голос
/ 06 марта 2019

Вот решение, которое более эффективно, чем решение, использующее group_by, в котором последнее включает в себя сортировку.

Эффективность может быть достигнута с помощью встроенного INDEX/1 и общей функции aggregate_by, определенной как:

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])
1 голос
/ 06 марта 2019

Вот простое решение с использованием group_by:

group_by(.code)
| map( reduce .[] as $x (.[0] | del(.name); 
         .people += [$x.name]) )
0 голосов
/ 06 марта 2019

для тех, кто может искать альтернативы, вот решение, основанное на jtc и стандартных утилитах Unix:

1. сначала рассортируем все уникальные code:

bash $ jtc -w'<code>l:' file.json | sort -u 
"AAA"
"BBB"
bash $

2. затем передайте каждое значение через xargs в jtc, чтобы объединить каждую запись по name (применяя результат на месте, переключите -f). Примечание: ниже опция xarg -t предоставляется только для демонстрационных целей и не требуется:

bash $ jtc -w'<code>l:' file.json | sort -u | xargs -L1 -I{} -t jtc -w"[code]:<{}>[-1][name]" -mi'[code]:<{}>1:[-1][name]' -f file.json
jtc -w[code]:<AAA>[-1][name] -mi[code]:<AAA>1:[-1][name] -f file.json
jtc -w[code]:<BBB>[-1][name] -mi[code]:<BBB>1:[-1][name] -f file.json
bash $ 

3. наконец удалите все объединенные записи:

bash $ jtc -w'<code>l:' file.json | sort -u | xargs -L1 -I{} -t jtc -w"[code]:<{}>1: [-1]" -p -f file.json
jtc -w[code]:<AAA>1: [-1] -p -f file.json
jtc -w[code]:<BBB>1: [-1] -p -f file.json
bash $ 

file.json теперь содержит желаемый результат:

bash $ cat file.json
[
   {
      "code": "AAA",
      "latitude": 11,
      "longitude": 22,
      "name": [
         "person 1",
         "person 2"
      ]
   },
   {
      "code": "BBB",
      "latitude": 33,
      "longitude": 44,
      "name": [
         "person 3",
         "person 4"
      ]
   }
]
bash $ 

***, если вы хотите переименовать метку name в people, примените дополнительный шаг:

bash $ jtc -w'<name>l: <>v' -u'"people"' file.json 
[
   {
      "code": "AAA",
      "latitude": 11,
      "longitude": 22,
      "people": [
         "person 1",
         "person 2"
      ]
   },
   {
      "code": "BBB",
      "latitude": 33,
      "longitude": 44,
      "people": [
         "person 3",
         "person 4"
      ]
   }
]
bash $ 

jtc руководство пользователя можно найти здесь: https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md

...