To compute a 7-day moving average:
J:
7 (+/%#)\ i.999
BQN:
(+´÷≠)˘7↕↕9
Python:
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
np.average(sliding_window_view(np.arange(0,1000,dtype=np.float64),7),axis=1)
Apple:
[((+)/x)%ℝ(:x)]`7 (frange 0 999 1000)
Performance
(10000000) 6!:2 '7 (+/%#) \ i.999'
1.82554e_6
)time:100000 (+´÷≠)˘7↕↕999
38.06us
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
%timeit np.average(sliding_window_view(np.arange(0,1000,dtype=np.float64),7),axis=1)
59.6 µs ± 366 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
> :bench [((+)/x)%ℝ(:x)]`7 (frange 0 999 1000)
benchmarking...
time 10.62 μs (10.58 μs .. 10.66 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 10.62 μs (10.59 μs .. 10.65 μs)
std dev 111.5 ns (94.66 ns .. 132.6 ns)
I suspect Python is slower because it allocates the entire intermediate array. In J (and Apple), we have an adverb which applies a verb to infixes directly; adroit choice of primitives make an array programming style feasible.