jq 为某些情况指定默认值
jq specify default value for some situation
现在我有一个 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)。例如
# 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]
那么如果age为0,如何给BJ
指定一个默认值0?
为清楚起见,合并同龄记录的辅助函数很有用。这是定义默认值的地方:
def merge:
reduce .[] as $x ([0,0];
if $x.city == "SH" then .[0] = $x.count else .[1] = $x.count end);
接下来,我们只需按年龄对记录进行分组:
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]}]
然后您可以按照您想要的方式格式化结果。
如果事先不知道相关的城市名称,那么如果城市名称是字符串,则以下方法值得推荐:
# 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":城市}
例如
{
"age": 40,
"data": {
"BJ": 0,
"SH": 1
}
}
现在可以轻松地将 CITIES 转换为所需的格式。
现在我有一个 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)。例如
# 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]
那么如果age为0,如何给BJ
指定一个默认值0?
为清楚起见,合并同龄记录的辅助函数很有用。这是定义默认值的地方:
def merge:
reduce .[] as $x ([0,0];
if $x.city == "SH" then .[0] = $x.count else .[1] = $x.count end);
接下来,我们只需按年龄对记录进行分组:
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]}]
然后您可以按照您想要的方式格式化结果。
如果事先不知道相关的城市名称,那么如果城市名称是字符串,则以下方法值得推荐:
# 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":城市}
例如
{
"age": 40,
"data": {
"BJ": 0,
"SH": 1
}
}
现在可以轻松地将 CITIES 转换为所需的格式。