2016-10-12 4 views
3

У меня есть более сложное выражение JQ, которое обрабатывает массив объектов.JQ: Уменьшить массив объектов до объекта, добавив в массив

вход выглядит следующим образом:

[ 
    { "key": "1", "value": "value 1"}, 
    { "key": "2", "value": "value 2"}, 
    { "key": "1", "value": "value 3"}, 
] 

То, что я хочу, чтобы это:

{ 
    "1": { "values": ["value 1", "value 3"] }, 
    "2": { "values": ["value 2"] } 
} 

или, для моего случая использования:

{ 
    "1": [ "value 1", "value 3" ], 
    "2": [ "value 2" ] 
} 

также будет ОК ,

Я уже пытался использовать … | { (.key): [.value] }, но результат (для меня не удивительно), что позднее появление ключей просто перезаписывает уже существующие. То, что я хочу выполнить, это нечто вроде «создать новую пару ключ/значение или добавить значение в уже существующий массив значений».

ответ

2

ОК, наконец, выяснив, что я хочу, я также понимаю, что мои предыдущие фильтры не сохранили входной массив, но привели к тому, что объекты выходили друг за другом. Таким образом, это было основной причиной, почему все найденные мной примеры не сработали.

Я хотел бы сгруппировать по ключам (отсюда требование ключа/значения), которое group_by уже делает, но не работает.

От группировки, работающей только на небольшом шаге к моему решению (уникальные ключи, значения в массивах).

'… group_by(.key) | map({ "key": .[0].key, "values": map(.value) | unique })' 

Выход теперь выглядит следующим образом, который прекрасно подходит для моих требований:

[ 
    { 
     "key": "1", 
     "values": [ 
      "value 1", 
      "value 3" 
     ], 
    }, 
    { 
     "key": "2", 
     "values": [ 
      "value 2" 
     ] 
    } 
] 
1

Недостатком решения, опирающегося на group_by что group_by требует сортировки, который не является необходимым здесь. В этом ответе я покажу, как избежать сортировки с помощью общей (и вообще полезной) функции jq, которая «объединяет» массив объектов JSON, по существу, выбирая значение каждого ключа в массив и затем объединяя соответствующие массивы.

# input should be an array of objects def meld: reduce .[] as $o ({}; reduce ($o|keys)[] as $key (.; .[$key] += [$o[$key]]));

Давайте также определить некоторые данные: def data: [ { "key": "1", "value": "value 1"}, { "key": "2", "value": "value 2"}, { "key": "1", "value": "value 3"} ] ;

Затем фильтр:

data | map([.] | from_entries) | meld 

производит:

{"1":["value 1","value 3"],"2":["value 2"]} 
Смежные вопросы