2017-06-12 85 views
1

現在我有一個JSONJQ指定默認值某些情況

[ 
    { 
    "city": "SH", 
    "age": 0, 
    "count": 1 
    }, 
    { 
    "city": "SH", 
    "age": 20, 
    "count": 1 
    }, 
    { 
    "city": "SH", 
    "age": 40, 
    "count": 1 
    }, 
    { 
    "city": "BJ", 
    "age": 20, 
    "count": 2 
    }, 
    { 
    "city": "BJ", 
    "age": 30, 
    "count": 1 
    } 
] 

現在,我想每一個時代的一些數據可視化的目的計數陣列(見demo)。 e.g

# age data: [shCount, bjCount] 
age: 0, data:[1, 0] 
age: 20, data: [1, 2] 
age: 30, data: [0, 1] 
age: 40, data: [1, 0] 

如果城市沒有年齡,給出一個默認值0。但是,如果城市沒有年齡,就沒有相關的JSON對象。

,所以我不能只是使用下面殼獲得計數每一個時代的陣列,e.g

# without BJ value 
➜ ~ jq -c '.[] | select(.age==0) | [.city, .count]' foo.json 
["SH",1] 

➜ ~ jq -c '.[] | select(.age==20) | [.city, .count]' foo.json 
["SH",1] 
["BJ",2] 

所以,如果年齡爲0,如何指定的0至BJ默認值?

回答

0

如果相關城市名事先不知道,那麼下面的方法有很多可取之處,如果城市名稱是字符串:

# Merge records having the same age 
def merge: 
    reduce .[] as $x ({}; . + ($x | { (.city) : .count})); 

# Create an object holding the default values: 
def zeros: 
    map({(tostring): 0}) | add; 

group_by(.age) 
| map({age: .[0].age, data: merge}) 
| (map(.data) | add | keys | zeros) as $zeros 
| map(.data = $zeros + .data) 

的上面的輸出是具有形式的對象數組: {「age」:_,「data」:CITIES}

eg

{ 
    "age": 40, 
    "data": { 
     "BJ": 0, 
     "SH": 1 
    } 
    } 

現在很容易將CITIES轉換爲所需的格式。

2

爲了清楚起見,用於合併同齡記錄的幫助函數很有用。這是默認值的定義:

group_by(.age) 
| map({age: .[0].age, data: merge}) 

調用:

jq -c -f program.jq input.json 

結果:

[{"age":0,"data":[1,0]},{"age":20,"data":[1,2]},{"age":30,"data":[0,1]},{"age":40,"data":[1,0]}] 

def merge: 
    reduce .[] as $x ([0,0]; 
    if $x.city == "SH" then .[0] = $x.count else .[1] = $x.count end); 

接下來,我們按年齡只需要組記錄

然後,您可以格式化結果無論你想要什麼樣的方式。

+0

謝謝,但我不能得到你的結果,但與錯誤消息:'jq:錯誤(在):不能迭代null(null)'。另外那裏有很多城市呢? – zhuguowei

+0

您可能想要在不帶-n選項的情況下調用jq。我已經相應地更新了答案。至於處理多個城市,我增加了另一個答案。 – peak