Remove duplicated Vector at dictionary in Julia - dictionary

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

Related

Traversing Nested Dicts in 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"]

How to append a value to a nested dictionary?

I'm trying to create a list nested within a dictionary and append values to it. In python, I would have written the following:
samples = {'x' : [1], 'y' : [-1]}
and to append values in a for-loop:
samples['x'].append(new_value)
How can I achieve something equivalent in Julia?
Here it is:
julia> samples = Dict("x" => [1], "y" => [-1])
Dict{String, Vector{Int64}} with 2 entries:
"x" => [1]
"y" => [-1]
julia> push!(samples["x"],4);
julia> samples
Dict{String, Vector{Int64}} with 2 entries:
"x" => [1, 4]
"y" => [-1]
Perhaps in Julia one would consider Symbols as keys instead of Strings so it could be samples = Dict(:x => [1], :y => [-1])
Finally, if you know that the keys are only x and y you would use a NamedTuple:
julia> samples2 = (x = [1], y = [-1])
(x = [1], y = [-1])
julia> typeof(samples2)
NamedTuple{(:x, :y), Tuple{Vector{Int64}, Vector{Int64}}}
julia> push!(samples2.x, 111);
julia> samples2
(x = [1, 111], y = [-1])

How can I add a new key value pair to an existing dictionary?

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"

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

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