Filter dict and change its keys

Is is possible to filter a dictionary and change its keys elegantly?

julia> dict = Dict{Tuple{Symbol,Symbol},Expr}((:X₁, :X₁) => :(σX(σ[1], X₁)), (:X₁, :X₂) => :(σX(σ[1], X₁)),(:X₂, :X₂) => :(σX(σ[2], X₂)),(:X₃, :X₃) => :(σX(σ[3], X₃)))
Dict{Tuple{Symbol,Symbol},Expr} with 4 entries:
  (:X₁, :X₁) => :(σX(σ[1], X₁))
  (:X₂, :X₂) => :(σX(σ[2], X₂))
  (:X₃, :X₃) => :(σX(σ[3], X₃))
  (:X₁, :X₂) => :(σX(σ[1], X₁))

julia> filter(p -> p.first[1] == :X₁, dict)
Dict{Tuple{Symbol,Symbol},Expr} with 2 entries:
  (:X₁, :X₁) => :(σX(σ[1], X₁))
  (:X₁, :X₂) => :(σX(σ[1], X₁))

I would like to obtain a dictionary with its keys changed using the p.first[2] as values, i.e.:

Dict{Symbol,Expr} with 2 entries:
  :X₁ => :(σX(σ[1], X₁))
  :X₂ => :(σX(σ[1], X₁))

I would do something like:

julia> Dict(k[2] => value for (k, value) in dict if k[1] ==  :X₁)
Dict{Symbol,Expr} with 2 entries:
  :X₂ => :(σX(σ[1], X₁))
  :X₁ => :(σX(σ[1], X₁))

With Dict I create a new Dictionary from the values of the previous one, with an if as filter.

2 Likes

So far I am using:

Dict(p.first[2] => p.second for p in filter(p -> p.first[1] == :X₁, dict))

which is similar, but I think I am creating an unnecessary dict in the middle.

Yes, it is similar (I am using the iterator over the dict instead instead of using a filter). In both cases, a new Dictionary is created. I think you cannot avoid it, because the first Dictionary, dict, has a different type than the desired output.

but besides the output dict, which is a new dict of different type, I think I am creating a new dict as output of the filter function. However, I am not sure because each object of this dictionary might be a reference of the input dictionary, not a copy.

Thanks!

Yes, you are right. My proposal uses less memory than your, maybe because you are creating a temporal dictionary using the filter. I think I am creating also copies, but I am not sure about how to avoid it.

You’re welcome.

2 Likes