DefaultDict and DefaultOrderedDict
A DefaultDict allows specification of a default value to return when a requested key is not in a dictionary.
While the implementation is slightly different, a DefaultDict
can be thought to provide a normal Dict
with a default value. A DefaultOrderedDict
does the same for an OrderedDict
.
Constructors:
DefaultDict(default, kv) # create a DefaultDict with a default value or function,
# optionally wrapping an existing dictionary
# or array of key-value pairs
DefaultDict{KeyType, ValueType}(default) # create a DefaultDict with Dict type (KeyType,ValueType)
DefaultOrderedDict(default, kv) # create a DefaultOrderedDict with a default value or function,
# optionally wrapping an existing dictionary
# or array of key-value pairs
DefaultOrderedDict{KeyType, ValueType}(default) # create a DefaultOrderedDict with Dict type (KeyType,ValueType)
All constructors also take a passkey::Bool=false
keyword argument which determines whether to pass along the key
argument when calling the default function. It has no effect when the key is just a value.
Examples using DefaultDict
:
julia> dd = DefaultDict(1) # create an (Any=>Any) DefaultDict with a default value of 1
DefaultDict{Any, Any, Int64}()
julia> dd = DefaultDict{AbstractString, Int}(0) # create a (AbstractString=>Int) DefaultDict with a default value of 0
DefaultDict{AbstractString, Int64, Int64}()
julia> d = Dict('a'=>1, 'b'=>2)
Dict{Char, Int64} with 2 entries: 'a' => 1 'b' => 2
julia> dd = DefaultDict(0, d) # provide a default value to an existing dictionary
DefaultDict{Char, Int64, Int64} with 2 entries: 'a' => 1 'b' => 2
julia> d['c'] # should raise a KeyError because 'c' key doesn't exist
ERROR: KeyError: key 'c' not found
julia> dd['c']
0
julia> dd = DefaultOrderedDict(time) # call time() to provide the default value for an OrderedDict
DefaultOrderedDict{Any, Any, typeof(time)}()
julia> dd = DefaultDict(Dict) # Create a dictionary of dictionaries - Dict() is called to provide the default value
DefaultDict{Any, Any, UnionAll}()
julia> dd = DefaultDict(()->myfunc()) # call function myfunc to provide the default value
DefaultDict{Any, Any, Main.var"#1#2"}()
These all create the same default dict
julia> dd = DefaultDict{AbstractString, Vector{Int}}(() -> Vector{Int}())
DefaultDict{AbstractString, Vector{Int64}, Main.var"#3#4"}()
julia> dd = DefaultDict{AbstractString, Vector{Int}}(() -> Int[])
DefaultDict{AbstractString, Vector{Int64}, Main.var"#5#6"}()
julia> dd = DefaultDict{AbstractString, Vector{Int}}(Vector{Int})
DefaultDict{AbstractString, Vector{Int64}, DataType}()
julia> push!(dd["A"], 1)
1-element Vector{Int64}: 1
julia> push!(dd["B"], 2)
1-element Vector{Int64}: 2
julia> dd
DefaultDict{AbstractString, Vector{Int64}, DataType} with 2 entries: "B" => [2] "A" => [1]
Create a Dictionary of type AbstractString=>DefaultDict{AbstractString, Int}
, where the default of the inner set of DefaultDict
s is zero
julia> dd = DefaultDict{AbstractString, DefaultDict}(() -> DefaultDict{AbstractString,Int}(0))
DefaultDict{AbstractString, DefaultDict, Main.var"#7#8"}()
Use DefaultDict
to cache an expensive function call, i.e., memoize
julia> dd = DefaultDict{AbstractString, Int}(passkey=true) do key len = length(key) sleep(len) return len end
DefaultDict{AbstractString, Int64, Main.var"#9#10"}()
julia> dd["hi"] # slow
2
julia> dd["ho"] # slow
2
julia> dd["hi"] # fast
2
Note that in the second-last example, we need to use a function to create each new DefaultDict
. If we forget, we will end up using the sameDefaultDict
for all default values:
julia> dd = DefaultDict{AbstractString, DefaultDict}(DefaultDict{AbstractString,Int}(0));
julia> dd["a"]
DefaultDict{AbstractString, Int64, Int64}()
julia> dd["b"]["a"] = 1
1
julia> dd["a"]
DefaultDict{AbstractString, Int64, Int64} with 1 entry: "a" => 1
To create a DefaultDict
which recursively calls itself you can write:
julia> rdict(args...) = DefaultDict(rdict, Dict{Any,Any}(args...))
rdict (generic function with 1 method)
julia> dd = rdict()
ERROR: UndefVarError: `DefaultDict` not defined
julia> dd["a"]["b"]["c"]
ERROR: UndefVarError: `dd` not defined
It's also possible to create a recursive DefaultDict
where the key is restricted:
julia> rdict(args...) = DefaultDict{String,Any,typeof(rdict)}(rdict, Dict{String,Any}(args...))
rdict (generic function with 1 method)
julia> dd = rdict()
ERROR: UndefVarError: `DefaultDict` not defined
julia> dd["a"]["b"]["c"]
ERROR: UndefVarError: `dd` not defined