`haskey` and `values()` show different realities? [SOLVED/CLOSED]


#1

Here is a MWE:

D = 3; L = 2000
vectors = [rand(L) for i in 1:D]
d = Dict{Vector{Int}, Int}()
minima = [minimum(v) for v in vectors]
ind = zeros(Int, D)
ε = 0.001
for j in 1:length(vectors[1])
  for k in 1:D
    ind[k] = Int(ceil((vectors[k][j] - minima[k])/ε))
  end
  haskey(d, ind) || (d[ind] = 0)
  d[ind] += 1
  if d[ind] == 0
    error("For ind=$ind, the dict had 0!")
  end
end
#return [val/L for val in values(d)]
vals = values(d)
RL = length(vals)
ret = zeros(Float64, RL)
i = 1
for val in vals
  val == 0 && error("val was 0")
  (x = val/L; x == 0) && error("val/L was 0")
  ret[i] = x
  i += 1
end

Running this code gives you error “val was 0”.
So what is happening here is that I get a dictionary with some of its values are 0. However, this cannot be correct, because the dictionary values are set with the lines:

haskey(d, ind) || (d[ind] = 0)
d[ind] += 1

therefore, if a key exists, its value must be at least 1.

What is happening here?


#2

Solved…?

I have seen by examining keys(d) that all the keys are the same… Clearly one cannot use Arrays for keys of a dictionary (or at least not mutate them).

By using ind = @SVector [Int(ceil((vectors[k][j] - minima[k])/ε)) for k in 1:D] instead, it works.

EDIT: If you run the above example with very low ε you get all the values to be 1 (this happens by chance, because probably the random numbers are well spread out).


#3

You can’t modify keys for a Dict.

On the one hand, this is perfectly obvious to everyone with a minimal exposure to basic data structures (it is a hash table), on the other hand, this comes up all the time, so perhaps a remark about it would be in order somewhere in the manual, or the docstring of Dict.