Newbie delete elements from array question

I have an 1-D array A and an array of integers index that contains some of the indices of array A. I want to compute a new array from A with the elements with indices in index removed. Is there a slick Julia way of doing this. The way I would do this is by concatenating the subarrays of A that do not contain the indices in index. If it helps the index array is sorted. What I am actually trying to do is remove from the array all consecutive pairs of elements that are equal starting at the beginning so that [1,1,1,2] would reduce to [1,2].

deleteat! should do what you want. (e.g. deleteat!([1,1,1,2], [2,3])==[1,2])

maybe you want unique:

julia> show(unique([1,1,1,2]))
[1, 2]

Thank you! Thank you! Thank you!

Okay, looking at the original post, unique may not be the goal, rather something like:

squish(v) = foldl((r,e)->(last(r)==e || push!(r,e); r), v; init=[v[1]])

squish([1,1,1,2])    # == [1,2]

Using this squish would be faster than calling deleteat! in almost all cases.

1 Like

My array are almost always less than 16 in length. Would this then still be faster than deleteat!?

Okay, 16 may still be enough for squish above to be faster. But to get real speed, you have to be a little more detailed:

function squish!(v)
    isempty(v) && return v
    i, e = 2, v[1]
    @inbounds for j in 2:length(v)
        new_e = v[j]
        new_e == e && continue
        v[i] = new_e
        i += 1
        e = new_e
    end
    return resize!(v, i-1)
end

This gets top speed, but mutates the input vector:

julia> v = [1,1,1,2];

julia> squish!(v)
2-element Vector{Int64}:
 1
 2

julia> @btime squish!(v) setup=(v = [1,1,1,2])
  4.131 ns (0 allocations: 0 bytes)
2-element Vector{Int64}:
 1
 2

To keep the input vector, use copy or the previous squish:

julia> squish!(copy(v))
2-element Vector{Int64}:
 1
 2

Thank you. I will be experimenting with everyone’s suggestions. For what it is worth I am calculating the geometric product of two bases in a geometric algebra. This requires reducing the integer list to normal order using certain rules. Each entry in the list refers to a basis vector in the algebra. For example [1,3,2] => exezey and [1] => ex, etc… The basis vectors are not necessarily orthogonal.

Ah… maybe something like this would interest you then:

freeprod(v) = foldl(v; init=Tuple{eltype(v),Int}[]) do r,e
    if isempty(r) || first(r[end])!=e
        push!(r, (e,1))
    else
        r[end] = (r[end][1], r[end][2]+1)
    end
    r
end

which gives:

julia> freeprod(v)
2-element Vector{Tuple{Int64, Int64}}:
 (1, 3)
 (2, 1)

a list of values and ‘exponents’.

Or, as an educational example, another way to code freeprod (which is slightly slower):

using IterTools

freeprod2(v) = Iterators.map(g->(first(g),length(g)),
  IterTools.groupby(identity, v)) |> collect

The way I understand the problem, unique! is the solution. Wait with complicated speed optimisations until you know that it will make a noticeable difference.

1 Like

Since you are being so helpful let me give you and example of what I am doing. For 3 dimensions the basis vectors are represents by [1]=>e_1, [2]=>e_2, and [3]=>e_3 and the dot products of the basis vectors (metric tensor) are g_ij = e_i⋅e_j. Then the basis of the geometric algebra is [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3] ([1,2,3]=>e_1e_2e_3)the geometric product of three vectors which is associative ) and an element of the algebra is linear combination of the basis vectors and a scalar and is called a multivector. To multiply multivectors we need to multiply bases and get an answer as a multivector. The reduction formula where a and b are vectors is ba = 2a⋅b-ab (Note that aa = 2a⋅a-aa or aa = a⋅a ). Then for example -


[1,2,3][1,2] = [1,2,3,1,2] = [1,2](2g_31-[1,3])[2] = 2g_31[1,2,2]-[1,2,1,3,2] = 2g_31g_22[1]-([1,2,1](2g_32-[2,3])) = 2g_31g_22[1]-2g_32[1,2,1]+[1,2,1,2,3] =

2g_31g_22[1]-2g_32(2g_21[1]-[1,1,2])+[1,2,1,2,3] = 2g_31g_22[1]-2g_32*2g_21[1]+4g_31g_22g_11[2]+[1,2,1,2,3]=

2g_31g_22[1]-2g_32*2g_21[1]+4g_31g_22g_11[2]+([1,2](2g_21-[2,1])[3]) = 2g_31g_22[1]-2g_32*2g_21[1]+4g_31g_22g_11[2]+2g_21[1,2,3]-[1,1,2,2,3] =

(2g_31g_22-2g_32*2g_21)[1]+4g_31g_22g_11[2]-g_11g_22[3]+2g_21[1,2,3]

or the simple examples


[2,1] = 2g_21 - [1,2]

[1,1] = g_11

[1,2,2] = g_22[1]