Suppose I write a function in Julia that takes a Dict{K,V}
as an argument, then creates arrays of type Array{K,1}
and Array{V,1}
. How can I extract the types K
and V
from the Dict object so that I can use them to create the arrays?
Sven and John's answers are both quite right. If you don't want to introduce method type parameters the way John's code does, you can use the eltype
function:
julia> d = ["foo"=>1, "bar"=>2]
["foo"=>1,"bar"=>2]
julia> eltype(d)
(ASCIIString,Int64)
julia> eltype(d)[1]
ASCIIString (constructor with 1 method)
julia> eltype(d)[2]
Int64
julia> eltype(keys(d))
ASCIIString (constructor with 1 method)
julia> eltype(values(d))
Int64
As you can see, there are a few ways to skin this cat, but I think that eltype(keys(d))
and eltype(values(d))
are by far the clearest and since the keys
and values
functions just return immutable view objects, the compiler is clever enough that this doesn't actually create any objects.
eltype(d)
now returns Pair{ASCIIString,Int64}
and eltype(d)[1]
no longer works. (Julia v0.4) –
Emelina keytype
and valtype
are built-ins as of v0.4, and take the place of eltype(d)[1]
and eltype(d)[2]
, respectively. –
Semblable eltype(d)[1]
no longer works, at least for dictionaries. I get the error: MethodError: Cannot `convert` an object of type Int64 to an object of type Pair{String,Int64}
, and the thing returned from eltype()
is a Pair{String,Int}
. That said, eltype(keys(d))
still works as expected –
Ostracism If you're writing a function that will do this for you, you can make the types a parameter of the function, which may save you some run-time lookups:
julia> function foo{K, V}(d::Dict{K, V}, n::Integer = 0)
keyarray = Array(K, n)
valarray = Array(V, n)
# MAGIC HAPPENS
return keyarray, valarray
end
foo (generic function with 2 methods)
julia> x, y = foo(["a" => 2, "b" => 3])
([],[])
julia> typeof(x)
Array{ASCIIString,1}
julia> typeof(y)
Array{Int64,1}
You can use keys
and values
in combination with typeof
:
# an example Dict{K, V}
d = Dict{Int64, ASCIIString}()
# K
typeof(keys(d))
Array{Int64,1}
# V
typeof(values(d))
Array{ASCIIString,1}
keys
and values
now return iterators, not arrays. You need to add in a call to collect
in newer versions of Julia to get an array out. –
Remise If you are just interested in the types, you can use eltype(d)
, or define even more specific functions
keytype{K}(d::Dict{K}) = K
valuetype{K,V}(d::Dict{K,V}) = V
and find the type immediately through
keytype(d)
valuetype(d)
As far as I understand, this should be pretty efficient because the compiler can deduce most of this at compile time.
For iterables, the eltype
approach that is already given in other answers works well enough. E.g.
julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol, Int64} with 2 entries:
:a => 1
:b => 2
julia> K, V = eltype(keys(d)), eltype(values(d))
(Symbol, Int64)
julia> K
Symbol
julia> V
Int64
This approach is generalisable to all iterables. However I would like to offer another approach which will generalise to other kinds of object (and still doesn't use the method type signature approach):
julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol, Int64} with 2 entries:
:a => 1
:b => 2
julia> typeof(d)
Dict{Symbol, Int64}
julia> K, V = typeof(d).parameters
svec(Symbol, Int64)
julia> K
Symbol
julia> V
Int64
You can see that the Dict{Symbol, Int64}
type has a field parameters
which you can unpack to obtain the type parameters. This works on struct
s too:
julia> struct MyStruct{S, T}
a::S
b::T
end
julia> x = MyStruct(1, 1.0)
MyStruct{Int64, Float64}(1, 1.0)
julia> S, T = typeof(x).parameters
svec(Int64, Float64)
julia> S
Int64
julia> T
Float64
© 2022 - 2024 — McMap. All rights reserved.