Traversing Nested Dicts in Julia - julia

I'm using the excellent Julia Mat File reader to read a mat file with the structure similar to test2
Dict1 = Dict("a" => [1,3], "b" => 2, "c" => "Hello")
test2=Dict("test"=>Dict1,"a"=>[2,4])
With the read command I can access Dict1 like this:
using MAT
read(file, "test")
But I'd also like to access variables within Dict1, like "a" or "b".
Any suggestions?
Thanks!

dict_1 = Dict("a" => [1,3], "b" => 2, "c" => "Hello")
dict_2 = Dict("test" => dict_1, "a" => [2,4])
#show dict_2["test"]["b"]

Related

Remove duplicated Vector at dictionary in Julia

I am looking for solution to remove duplicated value in vector which is in dictionary format at Julia.
Here is my dictionary :
x = Dict{AbstractString,Array{Integer,1}}("A" => [1,2,3], "B" => [3,4,5], "C" => [5,6,7])
and below is expected output :
Dict{AbstractString, Vector{Integer}} with 3 entries:
"A" => [1, 2]
"B" => [4]
"C" => [6, 7]
This is a relatively short way to do it (I have not optimized it for full speed to keep the solution short):
julia> using StatsBase
julia> x = Dict{AbstractString,Array{Integer,1}}("A" => [1,2,3], "B" => [3,4,5], "C" => [5,6,7])
Dict{AbstractString, Vector{Integer}} with 3 entries:
"B" => [3, 4, 5]
"A" => [1, 2, 3]
"C" => [5, 6, 7]
julia> dups = [k for (k, v) in countmap(Iterators.flatten(values(x))) if v > 1]
2-element Vector{Int64}:
5
3
julia> foreach(v -> setdiff!(v, dups), values(x))
julia> x
Dict{AbstractString, Vector{Integer}} with 3 entries:
"B" => [4]
"A" => [1, 2]
"C" => [6, 7]
If anything is not clear in the code please comment.
This solution updates your dictionary x in-place as I assumed this is what you wanted.
Or, pedestrian-style
allvalues(x::AbstractDict) = reduce(vcat, collect(values(x)))
function finddups(x::AbstractArray)
dups = Int[]
filter(item -> item in dups ? true : begin
push!(dups, item)
false end, x)
end
x = Dict{AbstractString,Array{Integer,1}}("A" => [1,2,3], "B" => [3,4,5], "C" => [5,6,7])
dups = x |> allvalues |> finddups
foreach(v -> setdiff!(v, dups), values(x))
x

Make SortedDict sorted by values in Julia

I am new to Julia and I've noticed it's not easy to Google for things which seem to be little more beyond elementary.
I would like to create an instance of SortedDict from DataStructures package but I want it to be sorted by values.
According to the documentation, the SortedDict takes parameter o which is some kind of comparator (order), so I guess I should create the one which does what I want.
SortedDict(o=Forward)
After some search, I've found how the Forward ordering is programmed here and I must admit it's hard to decipher for me.
I wanna have an instance of such a dict: SortedDict{String,Float64} and I want it to be sorted according to these Float64s.
Example:
(
"b" => 0.1,
"a" => 0.2,
"c" => 0.3
)
Could someone please tell me if this is possible and if so please indicate the solution?
The SortedDict type does seem to support sorting by value. An alternative could be to use OrderedDict from the OrderedCollections package (it is also reexported by the DataStructures package). It is ordered by insertion order, but it does allow you to sort it by value:
julia> o = OrderedDict("a" => 0.2, "b" => 0.1, "c" => 0.3)
OrderedDict{String,Float64} with 3 entries:
"a" => 0.2
"b" => 0.1
"c" => 0.3
julia> sort(o, byvalue=true)
OrderedDict{String,Float64} with 3 entries:
"b" => 0.1
"a" => 0.2
"c" => 0.3

Broadcasting algebraic operations between dicts

I have two dicts and I want to subtract the matching values from the two dicts to generate a third dict.
A = Dict("w" => 2, "x" => 3)
B = Dict("x" => 5, "w" => 7)
# Ideally I could go B .- A and get a dict like
C = Dict("w" => 5, "x" => 2)
# but I get ERROR: ArgumentError: broadcasting over dictionaries and `NamedTuple`s is reserved
One ugly solution is to overload the subtraction operator but I am not keen to overload for a builtin type like dict for fear of breaking other code.
import Base.-
function -(dictA::Dict, dictB::Dict)
keys_of_A = keys(dictA)
subtractions = get.(Ref(dictB), keys_of_A, 0) .- get.(Ref(dictA), keys_of_A, 0)
return Dict(keys_of_A .=> subtractions)
end
Is there a cleaner way to do algebraic operations on matching values from different dicts?
merge provides the result you want.
A = Dict("w" => 2, "x" => 3)
B = Dict("x" => 5, "w" => 7)
C = merge(-, B, A)
Dict{String,Int64} with 2 entries:
"w" => 5
"x" => 2
Note that merge performs a union of the two collections and combines common keys by performing the given operation. So, for example:
W = Dict("w" => 4)
merge(-, B, W)
Dict{String,Int64} with 2 entries:
"w" => 3
"x" => 5

How to initialize a dictionary in Julia?

When I tried to do:
d = {1:2, 3:10, 6:300, 2:1, 4:5}
I get the error:
syntax: { } vector syntax is discontinued
How to initialize a dictionary in Julia?
The {} syntax has been deprecated in julia for a while now. The way to construct a dict now is:
Given a single iterable argument, constructs a Dict whose key-value pairs are taken from 2-tuples (key,value) generated by the argument.
julia> Dict([("A", 1), ("B", 2)])
Dict{String,Int64} with 2 entries:
"B" => 2
"A" => 1
Alternatively, a sequence of pair arguments may be passed.
julia> Dict("A"=>1, "B"=>2)
Dict{String,Int64} with 2 entries:
"B" => 2
"A" => 1
(as quoted from the documentation, which can be obtained by pressing ? in the terminal to access the "help" mode, and then type Dict)

Unsupported or misplaced expression in Julia Dict

I tried to run this command
dict = Dict("a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5)
in Julia 0.3.2 (via https://try.jupyter.org/) and got this error:
unsupported or misplaced expression =>
while loading In[1], in expression starting on line 1
I understand from here that this notation for dicts should be ok.
What is wrong?
The syntax is slightly different in 0.3:
x= Dict({"a"=>5})
Note the curly brackets!
Whereas the code you wrote is 0.4 syntax. You can check the documents by changing the version number.
Just for reference the 0.4 syntax is:
x=Dict("a"=>5)
For those coming here who are using Julia 1.0.0, note that the OP's code now works:
julia> dict = Dict("a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5)
Dict{String,Int64} with 5 entries:
"c" => 3
"e" => 5
"b" => 2
"a" => 1
"d" => 4
julia> VERSION
v"1.0.0"
An example from the Julia 1.0.0 docs is below:
Alternatively, a sequence of pair arguments may be passed.
julia> Dict("A"=>1, "B"=>2)
Dict{String,Int64} with 2 entries:
"B" => 2
"A" => 1

Resources