Создать объект из потока объектов с ключом в JQ - PullRequest
0 голосов
/ 22 октября 2018

Это вопрос о командной строке json процессор jq .Это не о javascript или jQuery или что-либо еще с js и qs в его имени: -)

У меня есть такие входные данные, как:

{ "id": "person1", "name": "wilma", "age": "quite old"}
{ "id": "person2", "name": "fred"}
{ "id": "person1", "name": "betty", "x": "extra"}

Я хочу выводвот так:

{
   "person1": { "name": "betty", "age": "quite old", "x": "extra" },
   "person2": { "name": "fred" }
}

Я пробовал разные вещи!

Например,

jq -s '.[] | { (.id) : . }' <data

дает

{ "person1": { "id": "person1", "name": "wilma", "age": "quite old" }}
{ "person2": { "id": "person2", "name": "fred" }}
{ "person1": { "id": "person1", "name": "betty", "x": "extra" }}

Что-то вроде этого,за исключением того, что он выводит поток объектов вместо одного.Мне нужно объединить все эти объекты вместе.

jqplay.org пример

Я также пытался использовать group_by(.id)[]|add, который объединяет каждый элемент, но все равно приводит к потоку,https://jqplay.org/s/lh6QUQ0DO4

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Ах!Я понял!Или у меня есть одно решение - пожалуйста, напишите, если есть лучший способ.

jq -s '[group_by(.id)[]| add | { (.id) : . } ]|add' <data

https://jqplay.org/s/BfAdRBZUMW

  1. group_by группирует входы по их .id value и создает массив массивов - внутренние массивы - это значения, совпадающие по id.

  2. для каждой группы внутренние массивы передаются в add, что, посколькувнутренние массивы - это объекты, объединяющие их.

  3. То есть массив из 2 элементов.Мы передаем это конструктору объекта, который выбирает id в качестве ключа и весь элемент в качестве значения.Это все еще оставляет массив элементов.

  4. внешний [] (начинается в начале паттерна) говорит, что берет все те и передает его в add (снова), который объединяетконечные объекты, созданные в (3).

Это работает, но может быть более чистый путь.

EDIT

Это уродливее, но производиттот же результат и на ~ 24% быстрее в наборе данных 9 МБ.

jq -s 'reduce [.[]|{ (.id) : . }][] as $item ({}; . * $item )' <data

При этом используется reduce <list> as <$var> (<initiation>; <iteration>), начиная с пустого объекта {} и используя оператор объединения *, начинаяиз входящего элемента . создать выход.Я удивлен, что это быстрее, но я понимаю, что group_by делает что-то вроде, поэтому я предполагаю, что это дополнительное время.

0 голосов
/ 22 октября 2018

Вы можете настроить свою попытку следующим образом:

jq -s 'map({ (.id) : . }) | add' <data

Однако было бы более эффективно использовать inputs и reduce с параметром командной строки -n вместо -s.

Конечно, использование этого подхода может привести к коллизиям.

Возможно, вы также захотите добавить del(.id)

...