I have two separate dictionaries defined. I am wondering if there is an elegant, single expression way that I can merge these two dictionaries into one?
Yes, using the merge() function. Here's a quick example:
julia> a = Dict("One" => 1.0, "Two" => 2.0)
Dict{String,Float64} with 2 entries:
"One" => 1.0
"Two" => 2.0
julia> b = Dict("Three" => 3, "Four" => 4)
Dict{String,Int64} with 2 entries:
"Three" => 3
"Four" => 4
julia> c = merge(a, b)
Dict{String,Float64} with 4 entries:
"One" => 1.0
"Two" => 2.0
"Three" => 3.0
"Four" => 4.0
See the Julia docs here for more examples and functionality related to merge(). The merge function creates a new, separate dictionary and returns it. There is also a mutating merge! function which modifies its first argument:
julia> merge!(a, b)
Dict{String,Float64} with 4 entries:
"One" => 1.0
"Two" => 2.0
"Three" => 3.0
"Four" => 4.0
julia> a
Dict{String,Float64} with 4 entries:
"One" => 1.0
"Two" => 2.0
"Three" => 3.0
"Four" => 4.0
Note that merge! returns the merged array which is the original dictionary a modified.
Related
I want to remove a key-value pair from a dictionary.
I am creating a new dictionary for now:
julia> dict = Dict(1 => "one", 2 => "two")
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
julia> dict = Dict(k => v for (k, v) in dict if k != 2)
Dict{Int64,String} with 1 entry:
1 => "one"
But I want to update the existing dictionary instead. How can I do this in Julia?
delete! will remove a key-value pair from a dictionary if the key exists, and have no effect if the key does not exist. It returns a reference to the dictionary:
julia> dict = Dict(1 => "one", 2 => "two")
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
julia> delete!(dict, 1)
Dict{Int64,String} with 1 entry:
2 => "two"
Use pop! if you need to use the value associated with the key. However, it will error if the key does not exist:
julia> dict = Dict(1 => "one", 2 => "two");
julia> value = pop!(dict, 2)
"two"
julia> dict
Dict{Int64,String} with 1 entry:
1 => "one"
julia> value = pop!(dict, 2)
ERROR: KeyError: key 2 not found
You can avoid throwing an error with the three argument version of pop!. The third argument is a default value to return in case the key does not exist:
julia> dict = Dict(1 => "one", 2 => "two");
julia> value_or_default = pop!(dict, 2, nothing)
"two"
julia> dict
Dict{Int64,String} with 1 entry:
1 => "one"
julia> value_or_default = pop!(dict, 2, nothing)
Use filter! to bulk remove key-value pairs according to some predicate function:
julia> dict = Dict(1 => "one", 2 => "two", 3 => "three", 4 => "four");
julia> filter!(p -> iseven(p.first), dict)
Dict{Int64,String} with 2 entries:
4 => "four"
2 => "two"
I have some dictionary that already exists. I want to add a new key-value pair, but I do not want to create a new dictionary from scratch.
How can I add a new key-value pair to an existing dictionary in Julia?
Julia uses the common dict[key] = value syntax for setting a key-value pair:
julia> dict = Dict(1 => "one")
Dict{Int64,String} with 1 entry:
1 => "one"
julia> dict[2] = "two"
"two"
julia> dict
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
The same syntax will override a key-value pair if the key already exists:
julia> dict
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
julia> dict[1] = "foo"
"foo"
julia> dict
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "foo"
dict[key] = value is syntax for a setindex! call. Although not as common, you can call setindex! directly:
julia> dict = Dict(1 => "one")
Dict{Int64,String} with 1 entry:
1 => "one"
julia> setindex!(dict, "two", 2)
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
I want to key into a dictionary, but Julia throws an exception if the key does not exist. To avoid the exception, I first have to check if they key exists in the dictionary.
I'm using this custom function for now:
function has_some_key(dict, key)
for (k, v) in dict
if k == key
return true
end
end
return false
end
Is there a better way to determine if a dictionary has a mapping for a given key?
haskey will check whether some collection has a mapping for a given key:
julia> d
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
julia> haskey(d, 1)
true
julia> haskey(d, 3)
false
Another way, which might be viable depending on your use case, is to use get to provide a default value in case the key is not present:
julia> d = Dict(1 => "one", 2 => "two")
Dict{Int64,String} with 2 entries:
2 => "two"
1 => "one"
julia> get(d, 1, "zero")
"one"
julia> get(d, 3, "zero")
"zero"
There's also get!, which will store the default value for the queried key as well.
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
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