Я нашел следующий способ подсчета значений в произвольно структурированном JSON:
{
cat <<EOF
{
"a": 3,
"b": 4,
"c": 3,
"d": {
"e": 3
},
"f": 6
}
EOF
} | jq '[..
| if type == "object"
then select(.value)
else .
end
] | map(select(. == 3)) | length'
Есть ли более короткий способ рекурсивного подсчета в произвольно структурированном JSON?
Мне интересно, может быть, мне нужно использовать walk
, но я смог найти только следующее и не знал, как считать в конце:
{
cat <<EOF
{
"a": 3,
"b": 4,
"c": 3,
"d": {
"e": 3
},
"f": 6
}
EOF
} | jq '..
| walk(if type == "object"
then to_entries
| map(select(.value))
| from_entries
else .
end
)
| (. == 3)'
Урожайность:
false
true
false
true
false
true
false
Вы можете просмотреть представление потока, отфильтровать совпадающие элементы и подсчитать на лету:
jq 'reduce tostream[1] as $v (0; if $v == 3 then .+1 else . end)'
Точно так же вы можете рекурсивно выполнять итерацию, используя ..
, и учитывать только scalars
(или numbers
):
jq 'reduce (.. | scalars) as $v (0; if $v == 3 then .+1 else . end)'
Или переместите условие в генератор итераций, чтобы вы могли безоговорочно считать в теле:
jq 'reduce (.. | select(numbers == 3)) as $_ (0; .+1)'
Для подсчета часто полезно использовать общий фильтр:
def count(s): reduce s as $x (0; .+1);
count(tostream | select(length==2 and .[1] == $value))
где $value — процентная стоимость.
В этом конкретном случае вы также можете использовать параметр командной строки jq --stream
, например.
jq -n --argjson 3 --stream -f program.jq
где program.jq содержит указанное выше определение, за которым следует:
count(inputs | select(length==2 and .[1] == $value))
Использование параметра --stream было бы выгодно, если бы источник содержал большое значение JSON.
Вы можете использовать любое другое разрешенное имя для переменной «уменьшить», например. $_
Я это понимаю. Я предполагаю, что вы говорите, что независимо от того, как это называется, там должна быть переменная, даже если она не используется.
Спасибо за этот ответ! Я как бы понимаю, что делает код, беря его части и глядя на то, что получается. Кажется, что
count
не является встроеннымcount
. Это кажется примечательным. Или используя другое имя. Чего я пока не понимаю, так это почемуreduce
нужно создать$x
. Это просто требованиеjq
для корректности синтаксиса?