Как сгруппировать JSON по ключу и отсортировать по его количеству? - PullRequest
1 голос
/ 20 апреля 2020

Я начинаю с файла jsonlines, подобного этому

{ "kw": "foo", "age": 1}
{ "kw": "foo", "age": 1}
{ "kw": "foo", "age": 1}
{ "kw": "bar", "age": 1}
{ "kw": "bar", "age": 1}

Обратите внимание, что каждая строка является допустимой json, но весь файл не является.

Вывод Я search - упорядоченный список ключевых слов, отсортированный по его появлению. Например:

[
    {"kw": "foo", "count": 3},
    {"kw": "bar", "count": 2}
]

Я могу группировать и подсчитывать ключевые слова, используя параметр slurp

jq --slurp '. | group_by(.kw) | .[] | {kw: .[0].kw, count: . | length }'

Вывод:

{"kw":"bar","count":2}
{"kw":"foo","count":3}

Но:

  • Это не отсортировано
  • Это недопустимо JSON массив

Очень глупое решение, которое я нашел, - дважды пройти через jq :)

jq --slurp --compact-output '. | group_by(.kw) | .[] | {kw: .[0].kw, count: . | length }' sample.json \
| jq --slurp --compact-output '. | sort_by(.count)'

Но я уверен, что кто-то умнее меня сможет найти более элегантное решение.

1 Ответ

2 голосов
/ 20 апреля 2020

Это не отсортировано

Это не совсем правильно, group_by(.foo) внутренне делает sort(.foo), поэтому результаты отображаются в отсортированном порядке поля. См. jq Руководство - group_by (path_expression)

Это недопустимо JSON массив

Просто заключите операцию в [..] а также ведущий . не является обязательным. Так что просто сделайте

jq --slurp --compact-output '[ group_by(.kw)[] | {kw: .[0].kw, count: length } ]'

Если вы имеете в виду сортировку по .count, вы можете выполнить сортировку по возрастанию и повернуть ее в обратном порядке

jq --slurp --compact-output '[ group_by(.kw)[] | {kw: .[0].kw, count: length }] | sort_by(.count) | reverse'
...