`convert` an object of type Array{Any,1} to an object of type Float64

#1

Dear All,

is it possible that we convert an object of type Array{Any,1} to an object of type Float64:

rb = [0.0 0.0 1.0 1.0]
i=1
while i < length(rb)
  if (rb[i]==rb[i+1])
    rb[i+1]=[]
   global    i=i-1
   end
   global  i=i+1
end

Error:
ERROR: LoadError: MethodError: Cannotconvertan object of type Array{Any,1} to an object of type Float64

0 Likes

#2

I’m confused as to what you are trying to do. The reason you have a Array{Any,1} is because [] is an empty Vector without a type, and thus of type Any.

0 Likes

#3

I’m confused as to what you are trying to do.

Answer:
Delete repeated values in the vector.

0 Likes

#4

If you only need the first unique of each value, you can use unique!(rb).

EDIT: My alternative method had a mistake.

0 Likes

#5

The corret answer: is

rb =[0.0 1.0 ]

0 Likes

#6

unique!(rb)

ERROR: MethodError: no method matching _unique!(::Array{Float64,2})

You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
Closest candidates are:
  _unique!(::Any, ::AbstractArray{T,1} where T, ::Any, ::Set, ::Any) at set.jl:185
  _unique!(::Any, ::AbstractArray{T,1} where T, ::Set, ::Integer, ::Integer) at set.jl:248
  _unique!(::AbstractArray{T,1} where T) at set.jl:270
Stacktrace:
 [1] unique!(::Array{Float64,2}) at .\set.jl:343
 [2] top-level scope at none:0
0 Likes

#7

You entered a 2 dimension Array, rather than a 1D dimension

rb = [0.0 0.0 1.0 1.0]

If you want to enter a vector, you need the ,

rb = [0.0, 0.0, 1.0, 1.0]
unique(rb) == [0.0, 1.0]
1 Like

#8

thanks for your sharing anther method (command in julia) , but If I still want to use own loops in Julia, is it not possible and why we can not archive this simple loop in Julia?

rb = [0.0 0.0 1.0 1.0]
i=1
while i < length(rb)
  if (rb[i]==rb[i+1])
    rb[i+1]=[]
   global    i=i-1
   end
   global  i=i+1
end
0 Likes

#9
julia> rb = [0.0, 0.0, 1.0, 1.0]
4-element Array{Float64,1}:
 0.0
 0.0
 1.0
 1.0

julia> i=1
1

julia> while i < length(rb)
         global rb
         if (rb[i]==rb[i+1])
           rb = rb[1:length(rb) .!= i]
          global    i=i-1
          end
          global  i=i+1
       end

julia> rb
2-element Array{Float64,1}:
 0.0
 1.0
0 Likes

#10

This will skip the duplicates.

function removeduplicates(a)
    y=[a[1]]
    for i=2:length(a)
        a[i]!=y[end] && push!(y,a[i])
    end
    y
end

In Julia, you can’t remove from a vector by rb[i+1]=[]. You can either pop! to remove the last item, or deleteat! to remove a specific index. These functions do not work on a Array{T,2} because it is not logical to remove an item from an N x M matrix. Along with unique!, the ! indicates that it operates in place, similar to how your original function operates. rb = [0.0 0.0 1.0 1.0] is not a 1 dimensional Vector, but a 2D Matrix of size 1x4.

1 Like

#11

@Daniel_Berge and @Elrod,

Excellent. Thank you!

0 Likes

#12

I think you’re just looking for the deleteat! function:

function delete_repeated_sequential!(rb)
    i = 1
    while i < length(rb)
        if (rb[i] == rb[i + 1])
            deleteat!(rb, i + 1)
        else
            i += 1
        end
    end
    rb
end

delete_repeated_sequential!([0.0, 0.0, 1.0, 1.0])

Edit: ah, this was hinted at earlier.

1 Like

#13

I think in while loop, we have to use global i (Julia 1.1.0)?

0 Likes

#14

Only in global scope, not inside a function. In general, it’s a good idea to use functions. One reason is that it affords the compiler many more optimization opportunities. See https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-global-variables-1.

1 Like

#15

For efficiency reasons, I’d go the classical way of keeping a Boolean vector of valid indices and indexing into it.

function delete_successive(rb)
    indx = trues(length(rb))
    for i = 2:length(rb)
        indx[i] = rb[i] != rb[i-1]        
    end 
    rb[indx]
end  

rb = [0.0 0.0 1.0 1.0];
julia> delete_successive(rb)
2-element Array{Float64,1}:
 0.0
 1.0
1 Like

#16

Just for fun, a slightly more advanced way to solve this problem in Julia is to define your own iterator:

struct SkipRepeated{I}
    inner::I
end

# See https://docs.julialang.org/en/v1/base/collections/#lib-collections-iteration-1
function Base.iterate(x::SkipRepeated)
    state = iterate(x.inner)
    state === nothing && return nothing
    (val, _) = state
    (val, state)
end

function Base.iterate(x::SkipRepeated, state)
    (previous, innerstate) = state
    while true
        state = iterate(x.inner, innerstate)
        state === nothing && return nothing
        (val, innerstate) = state
        val != previous && return (val, state)
    end
end

Base.IteratorSize(::Type{<:SkipRepeated}) = Base.SizeUnknown()
Base.IteratorEltype(::Type{SkipRepeated{I}}) where {I} = Base.IteratorEltype(I)
Base.eltype(x::SkipRepeated) = eltype(x.inner)

which you can use as follows:

julia> rb = [1 1 2 3 3 3 0] # also works for your original row vector
1×7 Array{Int64,2}:
 1  1  2  3  3  3  0

julia> for x in SkipRepeated(rb)
            # simply iterating over SkipRepeated(rb) doesn't allocate a new vector
           @show x
       end

x = 1
x = 2
x = 3
x = 0

julia> collect(SkipRepeated(rb))
4-element Array{Int64,1}:
 1
 2
 3
 0
3 Likes