Is there diff() method for other operations?

question

#1

For example:

a = [ 2 , 4 , 8 , 16 , 32 ]

diff(a) 
=> [ 2 , 4 , 8 , 16 ]

How do you do this for other operations? This might include something like:

a = [ 2 , 4 , 8 , 16 , 32 ]

average(a)
=>  [ 3 , 6 , 12 , 24 ]

// for vectors this always reduces the length by one


#2

To evaluate f(x,y) for each two consecutive elements of a you can do

f.(@view(a[1:end-1]), @view(a[2:end]))

#3

Alternatively, you could define a generic consecutive function

function consecutive(f, A::AbstractVector)
    [ f(A[i+1], A[i]) for i = 1:length(A)-1 ]
end

a = [ 2 , 4 , 8 , 16 , 32 ]
consecutive(-, a)    # diff
consecutive(+, a)
consecutive(max, a)
consecutive((x,y)->(x+y)/2, a)    #average

#4

We’ve talked about this some on the GitHub issue tracker: check out https://github.com/JuliaLang/julia/issues/26361. There wasn’t enough of a consensus or drive to actually implement any of the proposed options.


#5

This package was created to solve that, and similar, problems


#6
using IterTools, Statistics
a = 2 .^ (1:5)
map(xs -> middle(xs...), partition(a, 2, 1))

#7

Note that the impetus for having such a function “built-in” in Julia is pretty low because writing an explicit comprehension or loop is easy and fast, and the impulse to use a consecutive(+, a) largely arises in Matlab-style vectorized code that is unnecessary (and usually awkward and suboptimal) in Julia.

Another generalization of this concept would be a convolution of a long sequence with a short sequence (in this case convolving A with [1,1], while diff corresponds to convolving with [1,-1]). This is nontrivial to implement extremely efficient code for in the general case of a length-m filter, so a mature library is helpful. Packages for this sort of thing include LocalFilters.jl and ImageFiltering.jl.