jq指定某些情况的默认值

时间:2017-06-12 11:02:36

标签: default-value jq

现在我有一个json

[
  {
    "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对象。

所以我不能只使用下面的shell来获取每个年龄的计数数组,例如

# 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

2 个答案:

答案 0 :(得分:2)

For clarity, a helper function for merging same-age records is useful. This is where the default values are defined:

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

Next, we have only to group records by age:

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

Invocation:

jq -c -f program.jq input.json

Result:

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

You can then format the result in whichever way you want.

答案 1 :(得分: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}

e.g。

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

现在很容易将CITIES转换为所需的格式。