JuliaDynamics / DrWatson.jl

The perfect sidekick to your scientific inquiries
https://juliadynamics.github.io/DrWatson.jl/stable/
Other
830 stars 93 forks source link

dict_list changes Dict type #327

Open msmerlak opened 2 years ago

msmerlak commented 2 years ago

A dict of type, say, {Symbol, Any} such as Dict{Symbol, Any}(:a => collect(1:10), :b => true) will be turned into a Vector{Dict{Symbol, Integer}}. This can create unwanted behavior.

I propose the following modification to _dict_list:

function _dict_list(c::AbstractDict)

    dict = typeof(c)

    iterable_fields = filter(k -> typeof(c[k]) <: Vector, keys(c))
    non_iterables = setdiff(keys(c), iterable_fields)

    iterable_dict = dict(iterable_fields .=> getindex.(Ref(c), iterable_fields))
    non_iterable_dict = dict(non_iterables .=> getindex.(Ref(c), non_iterables))

    vec(
        map(Iterators.product(values(iterable_dict)...)) do vals
            dd = [k=>convert(eltype(c[k]),v) for (k,v) in zip(keys(iterable_dict),vals)]
            if isempty(non_iterable_dict)
                Dict(dd)
            elseif isempty(iterable_dict)
                non_iterable_dict
            else
                # We can't use merge here because it promotes types.
                # The uniqueness of the dictionary keys is guaranteed.
                dict(dd..., collect(non_iterable_dict)...)
            end
        end
    )
end
sebastianpech commented 2 years ago

Yes, sounds reasonable to keep the original type. Could you open a PR?

Datseris commented 2 years ago

yEAH I agree this is a bug!