How to add values in a dictionary of lists?

Hello, good morning.
How to add values in a dictionary that has type (int, vector(int))? Cant understand the error about conversion

ERROR: LoadError: MethodError: Cannot `convert` an object of type Int64 to an object of type Vector{Tuple{Int64}}
using StatsBase
using Plots
using Combinatorics
using DataStructures

Ω = Dict((i, j) => i+j for i in 1:6 for j in 1:6);

println(length(Ω))
println(Ω)

buffer = DefaultDict{Int64, Vector{Tuple{Int64}}}(0);

for ((i,j), value) in Ω 
    println("Key: i: $i, j: $j -> $value")
    push!(buffer[value], (i, j));
end

You have probably mixed up your types you really want a bit, but for your

buffer = DefaultDict{Int64, Vector{Tuple{Int64}}}(0);

the proper push! would be e.g.:

julia> value=1
1

julia> i=2
2

julia> buffer = DefaultDict{Int64, Vector{Tuple{Int64}}}(0);

julia> push!( buffer, value => [(i,)] )
DefaultDict{Int64, Vector{Tuple{Int64}}, Int64} with 1 entry:
  1 => [(2,)]

But my guess is, you want something else.
I can just speculate but I think it helps, if you look what a Tuple{Int} really is:

julia> x=(1,)
(1,)

julia> typeof(x)
Tuple{Int64}

julia> y=(1,2)
(1, 2)

julia> typeof(y)
Tuple{Int64, Int64}

But perhaps you want to push into a Vector in the Dict, for this you first have to create the Vector, because

buffer[value]

isn’t defined in your case.
First check if

buffer[value]

exists:

haskey(buffer,value)

and if not create the Vector first:

v=[ (i,) ]
push!( buffer, value => v )

And if it exists, the push! would be e.g.:

push!( buffer[value], (4,) )
2 Likes

Thats a bit confusing…

for this

for ((i,j), value) in Ω 
    println("Key: i: $i, j: $j -> $value")
    push!(buffer, value => [(i, j)]);
end

got this error

ERROR: LoadError: MethodError: Cannot `convert` an object of type 
  Tuple{Int64{},Int64} to an object of type 
  Tuple{Int64{}}

What I want is create a key and append in vector of this key, because this will work as a histogram, and I will search for all the values of the vector using only the key

dict[7] will give-me all tuples (i,J) that i+j sums 7

For this you need:

buffer = DefaultDict{Int64, Vector{Tuple{Int64,Int64}}}(0);
1 Like

Now, it worked as you said.

DefaultDict(5 => [(2, 3)], 12 => [(6, 6)], 8 => [(5, 3)], 6 => [(2, 4)], 11 => [(6, 5)], 9 => [(5, 4)], 3 => [(2, 1)], 7 => [(6, 1)], 4 => [(2, 2)], 2 => [(1, 1)], 10 => [(5, 5)])

The issue was in the type declaration:

buffer = DefaultDict{Int64, Vector{Tuple{Int64}}}(0);

changing it to

buffer = DefaultDict{Int64, Vector{Tuple{Int64, Int64}}}(0);

worked

But your code has still an issue.
You will never have more than one tuple in any array, because you overwrite if a key already exist in your Dict. You have to check if a key already exist.

Isn’t the point of using a DefaultDict that you don’t have to check if a key already exists?

I imagine this is how the original code was supposed to look, i.e. getting both the value type and the default constructor right.

using DataStructures

Ω = Dict((i, j) => i+j for i in 1:6 for j in 1:6);

println(length(Ω))
println(Ω)

buffer = DefaultDict{Int, Vector{Tuple{Int, Int}}}(Vector{Tuple{Int, Int}});

for ((i,j), value) in Ω 
    println("Key: i: $i, j: $j -> $value")
    push!(buffer[value], (i, j));
end
3 Likes

yep, this leads to better code, and the issue root cause was the type declaration.

Didn’t know this and I didn’t look into the docs :wink:

1 Like