JQ добавить значение ключа во вложенном массиве и дать новый ключ

У меня есть поток массивов JSON, как это

[{"id":"AQ","Count":0}]
[{"id":"AR","Count":1},{"id":"AR","Count":3},{"id":"AR","Count":13},
{"id":"AR","Count":12},{"id":"AR","Count":5}]
[{"id":"AS","Count":0}]

Я хочу использовать JQ, чтобы получить новый JSON, как это

{"id":"AQ","Count":0}
{"id":"AR","Count":34}
{"id":"AS","Count":0}

34=1+3+13+12+5, которые находятся во втором массиве. Я не знаю, как описать это подробно. Но основная идея показана в моем примере. Я использую bash и предпочитаю использовать jq для решения этой проблемы. Спасибо!

3 ответа

Решение

Предполагая, что.id одинаков в каждом массиве:

first + {Count: map(.Count) | add}

Или, возможно, более доходчиво:

(map(.Count) | add) as $sum | first | .Count = $sum

Или более декларативно:

{ id: (first|.id), Count: (map(.Count) | add) }

Если вам нужно эффективное, но универсальное решение, которое НЕ предполагает, что каждый входной массив имеет одинаковые идентификаторы, то следующая вспомогательная функция упрощает решение:

# Input: a JSON object representing the subtotals
# Output: the object augmented with additional subtotals
def adder(stream; id; filter):
  reduce stream as $s (.; .[$s|id] += ($s|filter));

Предполагая, что ваш JQ имеет inputs, тогда наиболее эффективным подходом является его использование (но не забывайте использовать параметр командной строки -n):

reduce inputs as $row ({}; adder($row[]; .id; .Count) )

Это производит:

{"AQ":0,"AR":34,"AS":0}

Отсюда легко получить желаемый ответ, например, используя to_entries[] | {(.key): .value}

Если ваш JQ не имеет inputs и если вы не хотите обновляться, используйте опцию -s (вместо -n) и замените inputs от .[]

Это немного глупо, но учитывая ваш вклад:

jq -c '
  reduce .[] as $item ({}; .[($item.id)] += ($item.Count))
  | to_entries
  | .[] | {"id": .key, "Count": .value}
'

Выходит:

{"id":"AQ","Count":0}
{"id":"AR","Count":34}
{"id":"AS","Count":0}
Другие вопросы по тегам