[英]Extract all unique keys from arbitrarily nested json data with jq
如主題所述,我的目標是編寫all_keys
函數以從任意嵌套的json blob中提取所有鍵,並根據需要遍歷所包含的數組和對象,並輸出一個包含鍵的數組,而不重復。
例如,給定以下輸入:
[
{"name": "/", "children": [
{"name": "/bin", "children": [
{"name": "/bin/ls", "children": []},
{"name": "/bin/sh", "children": []}]},
{"name": "/home", "children": [
{"name": "/home/stephen", "children": [
{"name": "/home/stephen/jq", "children": []}]}]}]},
{"name": "/", "children": [
{"name": "/bin", "children": [
{"name": "/bin/ls", "children": []},
{"name": "/bin/sh", "children": []}]},
{"name": "/home", "children": [
{"name": "/home/stephen", "children": [
{"name": "/home/stephen/jq", "children": []}]}]}]}
]
all_keys
功能應該產生以下輸出:
[
"children",
"name"
]
為此,我設計了以下函數,但它的速度令人費解,所以我想知道您是否可以提出一種更簡潔,更快速的方法來獲得相同的結果。
def all_keys:
. as $in |
if type == "object" then
reduce keys[] as $k (
[];
. + [$k, ($in[$k] | all_keys)[]]
) | unique
elif type == "array" then (
reduce .[] as $i (
[];
. + ($i | all_keys)
) | unique
)
else
empty
end
;
作為參考,在我的Intel T9300@2.50GHz CPU上在53MB json文件上運行該功能大約需要22秒(我知道,它很古老,但仍然可以正常工作)。
天真的方法只會收集所有鍵並獲得唯一值。
[.. | objects | keys[]] | unique
但是對於這些數據,由於需要收集和排序密鑰,因此有點慢。
我們可以做得更好。 由於我們試圖確定所有不同的鍵,因此我們將使用某種哈希表來提高效率。 好吧,我們有可以充當對象的對象。
reduce (.. | objects | keys[]) as $k ({}; .[$k] = true) | keys
我沒有測量時間,但是比其他版本快很多。 我什至沒有等到另一個完成,這在我的工作計算機(i5-2400@3.1GHz)上不到10秒就可以完成。
我認為您會發現OP的all_keys的以下變體實際上比使用..
的版本稍快..
這可能是可以預期的-對於jeopardy.json, ..
總共生成1,731,807個JSON實體,而只有216,930個JSON對象:
def all_keys:
def uniquely(f): reduce f as $x ({}; .[$x] = true) | keys;
def rkeys:
if type == "object" then keys[] as $k | ($k, (.[$k]|rkeys))
elif type == "array" then .[]|rkeys
else empty
end;
uniquely(rkeys);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.