Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How recompute the eltype of a vector in Julia

Tags:

julia

Let's say I have a vector v = Any[1,2,3,4]

And I would like to recompute its eltype in such a way that typeof(v) = Vector{Int}

Is it possible to accomplish this without having to manually concatenate each of the elements in v?

like image 515
MPaga Avatar asked Dec 07 '22 10:12

MPaga


2 Answers

You can't "retype" the existing v, just create a copy of it with the more concrete type1.

Conversion

Assuming you already (statically) know the result type, you have multiple options. Most readable (and IMO, idiomatic) would be

Vector{Int}(v)

which is almost equivalent to

convert(Vector{Int}, v)

except that the latter does not copy if the input types is already the target type. Alternatively:

convert.(Int, v)

which surely copies as well.

What to convert to

If you don't know what the "common type" would be, there are multiple options how to get one that matches. In general, typejoin can be used to find a least upper bound:

mapreduce(typeof, typejoin, v; init=Union{})

The result will most likely be abstract, e.g. Real for an array of Ints and Float64s. So, for numeric types, you might be better off with promote_type:

mapreduce(typeof, promote_type, v; init=Union{})  # or init=Number

This at least gives you Float64 for mixed Ints and Float64s.

But all of this is not really recommended, since it might be fragile, surprising, and is certainly not type stable.


1For certain combinations of types, with compatible binary form, reinterpret will work and return a view with a different type, but this is only possible for bits types, which Any is not. For converting Any[1,2,3] to Int[1,2,3] copying is fundamentally necessary because the two arrays have different layouts in memory: the former is an array of pointers to individually allocated integers objects, whereas the latter stores the Int values inline in contiguous memory.

like image 120
phipsgabler Avatar answered Mar 15 '23 23:03

phipsgabler


If you don't know the output type, then consider using a comprehension

foo(v) = [x for x in v]

This is considerably faster on my computer than identity.(v):

julia> v = Any[1,2,3,4];

julia> @btime foo($v);
  153.018 ns (2 allocations: 128 bytes)

julia> @btime identity.($v);
  293.908 ns (5 allocations: 208 bytes)

julia> @btime foo(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);
  1.331 μs (2 allocations: 7.95 KiB)

julia> @btime identity.(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);
  25.498 μs (494 allocations: 15.67 KiB)
like image 20
DNF Avatar answered Mar 16 '23 00:03

DNF