Generate new key

question

#1

Is there a function/way to ask for a new unique key from an existing Dict that is not in already in the Dict? So I can safely assign to it knowing I’m not writing over something?
Thanks!


#2

What’s the key type? This works for numbers, at least:

keytype(di)

function new_key(di)
    local k
    while haskey(di, (k=rand(keytype(di));)) end
    k
end

new_key(Dict(1=>2))

#3

As @cstjean said, you need a general mechanism that generates random variates of a type T that is not in a given set. Then you just call it on keys(dict).

If the keys are sparse in T, just drawing until you get something new could be a quick & dirty method. Otherwise, if you have a total ordering, then the algorithms for sampling without replacement would be useful.


#4

I see.

Could you elaborate on that? I don’t have any restrictions on the key type, so I can make it work faster, I’d gladly do that.


#5

Perhaps you can give a bit more info about your use case. Does the keys have any meaning? How would you store them?


#6

Absolutely! Here’s some background:

I’m writing (as a part of a bigger program) a script that allows users to log (biology) experiments. So the user can set the levels of the treatments (e.g. the light regime can be dark, normal, or bright), and add, remove, and edit individual runs (e.g. run #1 had normal light regime).
I need to store a collection of these runs. I made a custom types to describe these runs. These custom types are initiated via a GUI, and stored in this collection. For the user to be able to delete or edit individual runs, I need to be able to refer to individual elements in that collection (things like replace and ). Since the content of the runs themselves is not enough to identify them, I need to rely on some other identifier. I could hash the whole type instance, but! These runs are not immutable. They can change, for instance when another run is deleted the repetition number of all the consecutive runs decrease by 1. So hashing them won’t work.

This is probably too vague and detailed at the same time. I apologize for that. I can give you a whole lot more details if you like…


#7

While this initially looks like a suboptimal solution since it could potentially be slow, in practice it’s probably ultra fast: how often would rand generate the same element in a huge unique collection of say Float64? Pretty unlikely… Right?


#8

Simply have a counter::Int which is incremented each time a run is added, making its current value the id for that run. Store runs in a Dict{Int,T}. Each new id will be unique, and it will be a long time before you run out of ids. You won’t need to worry about randomizing.


#9

Even if there’s a collision, it will generate a new one. I wouldn’t worry about it unless you have more than 2^60 runs. Also checkout Base.Random.uuid1()


#10

In reference to @Tamas_Papp, CardinalDicts.jl is extra well suited for this.