I’d like to avoid repeated lookup of the memory address of some key in a dictionary. Consider the following code:
function delete_if_even!(d::Dict, k)
if haskey(d, k) && iseven(d[k])
delete!(d, k)
else
d
end
end
Since a dictionary is implemented as a hash table, the hash computation happens 3 times in the above code, in haskey
, getindex
, and delete!
. The repeated computation can be avoid by rewriting the above function as follows, directly using ht_keyindex()
from dict.jl
,
function delete_if_even_fast!(d::Dict, k)
index = Base.ht_keyindex(d, k)
@inbounds index >= 0 && iseven(d.vals[index]) ? Base._delete!(d, index) : d # return d if nothing is done
end
In fact, a similar functionality is exported by the C++ stdlib unordered_map
. An iterator for the memory address of a key can be located by calling find()
, then you can directly delete a key using the iterator by calling erase()
. In Julia, the iterator of a dictionary is usually only produced by iterate()
unless you dig into unexported parts of dict.jl
. Or maybe there’s a more elegant solution to the problem?