Julia : construct Dictionary with tuple values - dictionary

Is there a possibility to construct dictionary with tuple values in Julia?
I tried
dict = Dict{Int64, (Int64, Int64)}()
dict = Dict{Int64, Tuple(Int64, Int64)}()
I also tried inserting tuple values but I was able to change them after so they were not tuples.
Any idea?
Edit:
parallel_check = Dict{Any, (Any, Any)}()
for i in 1:10
dict[i] = (i+41, i+41)
end
dict[1][2] = 1 # not able to change this way, setindex error!
dict[1] = (3, 5) # this is acceptable. why?

The syntax for tuple types (i.e. the types of tuples) changed from (Int64,Int64) in version 0.3 and earlier to Tuple{Int64,Int64} in 0.4. Note the curly braces, not parens around Int64,Int64. You can also discover this at the REPL by applying the typeof function to an example tuple:
julia> typeof((1,2))
Tuple{Int64,Int64}
So you can construct the dictionary you want like this:
julia> dict = Dict{Int64,Tuple{Int64,Int64}}()
Dict{Int64,Tuple{Int64,Int64}} with 0 entries
julia> dict[1] = (2,3)
(2,3)
julia> dict[2.0] = (3.0,4)
(3.0,4)
julia> dict
Dict{Int64,Tuple{Int64,Int64}} with 2 entries:
2 => (3,4)
1 => (2,3)
The other part of your question is unrelated, but I'll answer it here anyway: tuples are immutable – you cannot change one of the elements in a tuple. Dictionaries, on the other hand are mutable, so you can assign an entirely new tuple value to a slot in a dictionary. In other words, when you write dict[1] = (3,5) you are assigning into dict, which is ok, but when you write dict[1][2] = 1 you are assigning into the tuple at position 1 in dict which is not ok.

Related

How to get the empty entries from a Dictionary in Julia?

I have some dictionary I have defined which might have values that are empty. Is there a quick way to check to see if any of my key value pairs contain empty entries?
julia> a = Dict(1=>[1,2], 4=>[3,4], 6=>[])
Dict{Int64, Vector{T} where T} with 3 entries:
4 => [3, 4]
6 => Any[]
1 => [1, 2]
You wanted a quick way thus I would recommend:
findall(isempty, a)
One possible concise solution it to use a comprehension and the isempty function which will check this for you as follows:
julia> [k for (k,v) in a if isempty(v)]
1-element Vector{Int64}:
6
julia> filter(p->isempty(p.second), a)
Dict{Int64, Vector{T} where T} with 1 entry:
6 => Any[]
filter takes a function as its first argument and can take a Dictionary as its second argument.
The function is given a Pair of key-value pairs, which has members first (the key) and second (the value). So here, we filter by an anonymous function that checks whether p.second, i.e. the value, isempty, and return only those Pairs where that returns true.
An equivalent, and perhaps better looking, way to do this is:
julia> filter(isempty∘last, a)
Dict{Int64, Vector{T} where T} with 1 entry:
6 => Any[]
And for completeness' sake, if you want to just "check to see if" any of them are empty, you can take a count instead:
if count(isempty∘last, a) > 0
dosomething()
end

Why (; [(:x, 1), (:y, 2)]...) creates a NamedTuple?

I'm still learning Julia, and I recently came across the following code excerpt that flummoxed me:
res = (; [(:x, 10), (:y, 20)]...) # why the semicolon in front?
println(res) # (x = 10, y = 20)
println(typeof(res)) # NamedTuple{(:x, :y), Tuple{Int64, Int64}}
I understand the "splat" operator ..., but what happens when the semicolon appear first in a tuple? In other words, how does putting a semicolon in (; [(:x, 10), (:y, 20)]...) create a NamedTuple? Is this some undocumented feature/trick?
Thanks for any pointers.
Yes, this is actually a documented feature, but perhaps not a very well known one. As the documentation for NamedTuple notes:
help?> NamedTuple
search: NamedTuple #NamedTuple
NamedTuple
NamedTuples are, as their name suggests, named Tuples. That is, they're a tuple-like
collection of values, where each entry has a unique name, represented as a Symbol.
Like Tuples, NamedTuples are immutable; neither the names nor the values can be
modified in place after construction.
Accessing the value associated with a name in a named tuple can be done using field
access syntax, e.g. x.a, or using getindex, e.g. x[:a]. A tuple of the names can be
obtained using keys, and a tuple of the values can be obtained using values.
[... some other non-relevant parts of the documentation omitted ...]
In a similar fashion as to how one can define keyword arguments programmatically, a
named tuple can be created by giving a pair name::Symbol => value or splatting an
iterator yielding such pairs after a semicolon inside a tuple literal:
julia> (; :a => 1)
(a = 1,)
julia> keys = (:a, :b, :c); values = (1, 2, 3);
julia> (; zip(keys, values)...)
(a = 1, b = 2, c = 3)
As in keyword arguments, identifiers and dot expressions imply names:
julia> x = 0
0
julia> t = (; x)
(x = 0,)
julia> (; t.x)
(x = 0,)

How to pass Dict as the argument to method Julia

Hello i trying create converter method from Disct to Vector in Julia language.
But i receive error, with i can't understand
ERROR: TypeError: Tuple: in parameter, expected Type{T}, got Dict{AbstractString,Int64}
My code
type Family
name::UTF8String
value::Int
end
function convertToVector(a1::Dict{AbstractString, Int64}())
A::Vector{Node}
for k in sort(collect(keys(a1)))
push!(A, Family(a1[k] , k))
end
return A
end
Any idea hot to change convertToVector method ?
There were several typos in the above code, but I think this should work:
# No () after the type of a1
# Also, see comment, better to parameterize function, use concrete type for Dict
function convertToVector{T<:AbstractString}(a1::Dict{T, Int64})
# This is how you create an empty vector to hold Family objects
A = Vector{Family}()
for k in sort(collect(keys(a1)))
# The values passed to the Family constructor were backwards
push!(A, Family(k, a1[k]))
end
A
end
Another way (probably not very quick):
julia> dict = Dict("fred" => 3, "jim" => 4)
Dict{ASCIIString,Int64} with 2 entries:
"fred" => 3
"jim" => 4
julia> Vector{Family}(map(f -> Family(f...), map(x -> collect(x), dict)))
2-element Array{Family,1}:
Family("fred",3)
Family("jim",4)
Perhaps I've been using too much Lisp recently...

Check if an Object is an Array or a Dict

I'd like to check if var is an Array or a Dict.
typeof(var) == Dict
typeof(var) == Array
But it doesn't work because typeof is too precise: Dict{ASCIIString,Int64}.
What's the best way ?
If you need a "less precise" check, you may want to consider using the isa() function, like this:
julia> d = Dict([("A", 1), ("B", 2)])
julia> isa(d, Dict)
true
julia> isa(d, Array)
false
julia> a = rand(1,2,3);
julia> isa(a, Dict)
false
julia> isa(a, Array)
true
The isa() function could then be used in control flow constructs, like this:
julia> if isa(d, Dict)
println("I'm a dictionary!")
end
I'm a dictionary!
julia> if isa(a, Array)
println("I'm an array!")
end
I'm an array!
Note: Tested with Julia 0.4.3
Instead of checking for a particular concrete type, such as Array, or Dict, you might do better by checking for the abstract types, and gain a lot of flexibility.
For example:
julia> x = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> d = Dict(:a=>1,:b=>2)
Dict(:a=>1,:b=>2)
julia> isa(d, Associative)
true
julia> isa(x, AbstractArray)
true
There are many different types of arrays in Julia, so checking for Array is likely to be too restrictive, you won't get sparse matrices, for example.
There are also a number of different types of associative structures, Dict, ObjectIdDict, SortedDict, OrderedDict.

Convert Dict to DataFrame in Julia

Suppose I have a Dict defined as follows:
x = Dict{AbstractString,Array{Integer,1}}("A" => [1,2,3], "B" => [4,5,6])
I want to convert this to a DataFrame object (from the DataFrames module). Constructing a DataFrame has a similar syntax to constructing a dictionary. For example, the above dictionary could be manually constructed as a data frame as follows:
DataFrame(A = [1,2,3], B = [4,5,6])
I haven't found a direct way to get from a dictionary to a data frame but I figured one could exploit the syntactic similarity and write a macro to do this. The following doesn't work at all but it illustrates the approach I had in mind:
macro dict_to_df(x)
typeof(eval(x)) <: Dict || throw(ArgumentError("Expected Dict"))
return quote
DataFrame(
for k in keys(eval(x))
#eval ($k) = $(eval(x)[$k])
end
)
end
end
I also tried writing this as a function, which does work when all dictionary values have the same length:
function dict_to_df(x::Dict)
s = "DataFrame("
for k in keys(x)
v = x[k]
if typeof(v) <: AbstractString
v = string('"', v, '"')
end
s *= "$(k) = $(v),"
end
s = chop(s) * ")"
return eval(parse(s))
end
Is there a better, faster, or more idiomatic approach to this?
Another method could be
DataFrame(Any[values(x)...],Symbol[map(symbol,keys(x))...])
It was a bit tricky to get the types in order to access the right constructor. To get a list of the constructors for DataFrames I used methods(DataFrame).
The DataFrame(a=[1,2,3]) way of creating a DataFrame uses keyword arguments. To use splatting (...) for keyword arguments the keys need to be symbols. In the example x has strings, but these can be converted to symbols. In code, this is:
DataFrame(;[Symbol(k)=>v for (k,v) in x]...)
Finally, things would be cleaner if x had originally been with symbols. Then the code would go:
x = Dict{Symbol,Array{Integer,1}}(:A => [1,2,3], :B => [4,5,6])
df = DataFrame(;x...)

Resources