jq 中的累计和
Cumulative sum in jq
我在数组中有一系列 [timestamp, count]
对,我想使用 jq
计算每个时间戳的累积和。我该怎么做?
这里是一个示例数据集:
[
[1431047957699, 1],
[1431047958269, 1],
[1431047958901, 1],
[1431047959147, -1],
[1431047960164, 1]
]
预期结果:
[1431047957699, 1],
[1431047958269, 2],
[1431047958901, 3],
[1431047959147, 2],
[1431047960164, 3]
是否可以用 jq
做到这一点?
对此采用函数式方法并创建一个更新函数,该函数将使用累积总和创建更新值。
def accumulate(acc):
select(length > 0) |
(.[0][1] + acc) as $next |
(.[0] | .[1] = $next), (.[1:] | accumulate($next))
;
[accumulate(0)]
在这里,我们将数组分成 "head" 和 "tail" 用当前总和更新头部并递归更新尾部。结果被放回一个新数组中。
以下是非常通用的(例如,它可以与对象数组一起使用):
def accumulate(f):
reduce .[1:][] as $row
([.[0]];
. as $x
| $x + [ $row | (f = ($x | .[length-1] | f) + ($row|f) ) ] );
accumulate(.[1])
如果您使用的是足够新的 jq 版本,那么“$x |
.[length-1]”可以简化为“$x[-1]”。
使用foreach的解决方案
如果你的jq有foreach,那么可以使用下面的变体。如果需要值流而不是数组,这将特别合适。
def accumulates(f):
foreach .[] as $row
(0;
. + ($row | f) ;
. as $x | $row | (f = $x));
用法:
对于流:accumulates(.[0])
对于数组:[accumulates(.[0])
我在数组中有一系列 [timestamp, count]
对,我想使用 jq
计算每个时间戳的累积和。我该怎么做?
这里是一个示例数据集:
[
[1431047957699, 1],
[1431047958269, 1],
[1431047958901, 1],
[1431047959147, -1],
[1431047960164, 1]
]
预期结果:
[1431047957699, 1],
[1431047958269, 2],
[1431047958901, 3],
[1431047959147, 2],
[1431047960164, 3]
是否可以用 jq
做到这一点?
对此采用函数式方法并创建一个更新函数,该函数将使用累积总和创建更新值。
def accumulate(acc):
select(length > 0) |
(.[0][1] + acc) as $next |
(.[0] | .[1] = $next), (.[1:] | accumulate($next))
;
[accumulate(0)]
在这里,我们将数组分成 "head" 和 "tail" 用当前总和更新头部并递归更新尾部。结果被放回一个新数组中。
以下是非常通用的(例如,它可以与对象数组一起使用):
def accumulate(f):
reduce .[1:][] as $row
([.[0]];
. as $x
| $x + [ $row | (f = ($x | .[length-1] | f) + ($row|f) ) ] );
accumulate(.[1])
如果您使用的是足够新的 jq 版本,那么“$x | .[length-1]”可以简化为“$x[-1]”。
使用foreach的解决方案
如果你的jq有foreach,那么可以使用下面的变体。如果需要值流而不是数组,这将特别合适。
def accumulates(f):
foreach .[] as $row
(0;
. + ($row | f) ;
. as $x | $row | (f = $x));
用法:
对于流:accumulates(.[0])
对于数组:[accumulates(.[0])