web-dev-qa-db-ja.com

jqは特定のキーでjsonのアイテム数を数えます

以下は私のjsonファイルの最初の2つのアイテムです

{
"ReferringUrl": "N",
"OpenAccess": "0",
"Properties": {
    "ItmId": "1694738780"
   }
}
{
"ReferringUrl": "L",
"OpenAccess": "1",
"Properties": {
    "ItmId": "1347809133"
  }
}

Jsonに表示された各ItmIdごとにアイテムの数をカウントしたいと思います。たとえば、「ItmId」が1694738780のアイテムは10回出現し、「ItmId」が1347809133のアイテムはjsonファイルに14回出現します。次に、このようなjsonを返します

{"ItemId": "1694738780",
 "Count":  10
}
{"ItemId": "1347809133",
 "Count":  14
}

私はbashを使用しています。そして、これを完全にjqで行うことをお勧めします。ただし、他の方法を使用しても問題ありません。

ありがとうございました!!!

9
Eleanor

これが1つの解決策(入力が有効なJSONオブジェクトのストリームであると想定)であり、-sオプションを使用してjqを呼び出します。

map({ItemId: .Properties.ItmId})             # extract the ItmID values
| group_by(.ItemId)                          # group by "ItemId"
| map({ItemId: .[0].ItemId, Count: length})  # store the counts
| .[]                                        # convert to a stream

少しメモリ効率のよいアプローチは、jqにinputsを使用することです。ただし、その場合は、-sの代わりに-nを使用し、上記の最初の行を次のように置き換えます。 {ItemId:.Properties.ItmId}]

効率的なソリューション

上記のソリューションは組み込みgroup_by、これは便利ですが、簡単に回避できる非効率につながります。次のcounterを使用すると、非常に効率的なソリューションを簡単に作成できます。

def counter(stream):
  reduce stream as $s ({}; .[$s|tostring] += 1);

-nコマンドラインオプションを使用し、次のように適用します。

counter(inputs | .Properties.ItmId)

これはカウントの辞書につながります:

{
  "1694738780": 1,
  "1347809133": 1
}

このようなディクショナリは、OPによって想定されているシングルトンオブジェクトのストリームよりもおそらく便利ですが、ストリームなどが必要な場合は、上記を次のように変更できます。

counter(inputs | .Properties.ItmId)
| to_entries[]
| {ItemId: (.key), Count: .value}
11
peak

Jqコマンドの使用

cat json.txt | jq '.Properties .ItmId' | sort | uniq -c | awk -F " " '{print "{\"ItmId\":" $2 ",\"count\":" $1"}"}'| jq .
3
skr

reducesetpathおよびgetpathを使用して集計を行い、to_entriesを使用して最終的なフォーマットを行うバリエーションを以下に示します。あなたがjqを実行することを前提としています

jq --Slurp -f query.jq < data.json

ここでdata.jsonにはデータが含まれ、query.jqには

  map(.Properties.ItmId)
| reduce .[] as $i (
    {}; setpath([$i]; getpath([$i]) + 1)
  )
| to_entries | .[] | { "ItemId": .key, "Count": .value }
1
jq170727

これは非常に効率的なソリューションです。特に、並べ替えは必要ありません。次の実装では、inputsを使用したバージョンのjqが必要ですが、以前のバージョンのjqを使用するようにプログラムを適合させることは簡単です。以下を使用する場合は、必ず-nコマンドラインオプションを使用してください。

# Count the occurrences of distinct values of (stream|tostring).
# To avoid unwanted collisions, or to recover the exact values,
# consider using tojson
def counter(stream):
  reduce stream as $s ({}; .[$s|tostring] += 1);

counter(inputs | .Properties.ItmId)
| to_entries[]
| {ItemId: (.key), Count: .value}
1
peak