对于一个简单的键值对列表JSON,使用jq按值的范围打印摘要

xv8emn3q  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(89)

考虑下面的JSON有一个键值对列表

{
  "session1": 128,
  "session2": 1048596,
  "session3": 3145728,
  "session4": 3145828,
  "session5": 11534338,
  "session6": 11544336,
  "session7": 2097252
}

字符串
键是会话标识符,值是存储在会话中的值的长度。
我想打印计数值的范围-范围是(下限包括,上限排除); 0-1MB,1-2MB,2-3MB,... 12-13MB。

1MB =  1048576
 2MB =  2097152
 3MB =  3145728
 4MB =  4194304
 5MB =  5242880
 6MB =  6291456
 7MB =  7340032
 8MB =  8388608
 9MB =  9437184
10MB = 10485760
11MB = 11534336
12MB = 12582912
13MB = 13631488


预期输出为

{
  "0-1MB": 1,
  "1-2MB": 1,
  "2-3MB": 1,
  "3-4MB": 2,
  "10-11MB": 2
}


以上只是代表性的,欢迎大家提出建议。

hs1rzwqc

hs1rzwqc1#

以下内容应该有效:

to_entries
| map(.value / 1048576 | floor | [tostring, "-", (.+1 | tostring), "MB"] | add)
| group_by(.)
| map({"key": .[0], "value": length})
| from_entries

字符串
对于您的输入,它会生成以下输出:

{
  "0-1MB": 1,
  "1-2MB": 1,
  "11-12MB": 2,
  "2-3MB": 1,
  "3-4MB": 2
}


(11534338和11544336被计算在“11- 12 MB”存储桶中,而不是“10- 11 MB”存储桶中,因为11*2^20 = 11534336,而这些数字比这个数字大。
如果你想要这些键按数字顺序排列,你也可以把它们转换成你喜欢的group_by后面的字符串标签:

to_entries
| map(.value / 1048576 | floor)
| group_by(.)
| map({"key": [(.[0] | tostring), "-", (.[0]+1 | tostring), "MB"] | add, "value": length})
| from_entries


它产生:

{
  "0-1MB": 1,
  "1-2MB": 1,
  "2-3MB": 1,
  "3-4MB": 2,
  "11-12MB": 2
}


两种解决方案具有相同的基本步骤:
1.将输入对象转换为{"key": x, "value": y}项的数组(to_entries)。
1.通过向下舍入到最近的兆字节(.value / 1048576 | floor),将条目Map到标识它们所在范围的内容中。
1.按值(group_by)分组。这将为您的输入生成一个类似[[0], [1], [2], [3, 3], [11, 11]]的数组。
1.对于每个组,生成一个条目,其中“key”字段是范围标签(“X-YMB”),“value”是组中元素的数量(length)。
1.将条目列表转换回单个对象(from_entries)。

eulz3vhy

eulz3vhy2#

这里有一个使用reduce的方法,它简单地迭代输入值,并将相应的结果字段依次递增1。

reduce (.[] / 1048576 | floor) as $k ({}; ."\($k)-\($k+1)MB" += 1)

个字符
Demo
当然,可以首先对迭代的数字流进行排序,以获得具有递增字段名称的对象:

reduce (map(.) | sort[] / 1048576 | floor) as $k ({}; ."\($k)-\($k+1)MB" += 1)
{
  "0-1MB": 1,
  "1-2MB": 1,
  "2-3MB": 1,
  "3-4MB": 2,
  "11-12MB": 2
}

的字符串
Demo

相关问题