# Dictionary - inverse and consolidating

**URL:** <https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378>\
**Category:** New to Julia\
**Tags:** question, dictionary\
**Created:** [July 1, 2020, 3:23pm UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378 "2020-07-01T15:23:09Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Orr\_Orovan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/orr_orovan/32/15538_2.png) [@Orr\_Orovan](https://discourse.julialang.org/u/Orr_Orovan)\
**Post date:** [July 1, 2020, 3:23pm UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/1 "2020-07-01T15:23:09Z")

</div>

I have found this solution in Python and want to write in Julia something that will yield the same end result.

It inverses the keys and values in a dictionary and consolidate the values in the inverse dictionary into lists that hold what was keys in the original dictionary, that had the same values.

This example says it all, (in Python syntax):

> > > orig\_dict # the original dictionary  
> > > {‘one’: 10, ‘two’: 20, ‘three’: 20, ‘four’: 10, ‘five’: 30}

> > > inverted\_dict # the inverted dictionary  
> > > {10: [‘one’, ‘four’], 20: [‘two’, ‘three’], 30: [‘five’]}

And here is the Python code that makes this inversion:

```julia
inverted_my_dict = {}
    for key, value in my_dict.items():
        inverted_my_dict.setdefault(value, list()).append(key)

```

The iteration line in Julia:  
`for (k, v) in my_dict`

Asking for help here with the next step, the one that does the inverse and consolidation work. It is a one line in Python but it does two things.  
How would you write something in Julia that will produce the same result?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 1, 2020, 3:48pm UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/2 "2020-07-01T15:48:11Z")

</div>

Something like:

```julia
my_dict = Dict("one" => 10, "two" => 20, "three" => 20, "four" => 10, "five" => 30)
inverted_dict = Dict{valtype(my_dict), Vector{keytype(my_dict)}}()

for (k, v) in my_dict
    push!(get!(() -> valtype(inverted_dict)[], inverted_dict, v), k)
end

```

```julia
julia> inverted_dict
Dict{Int64,Array{String,1}} with 3 entries:
  30 => ["five"]
  10 => ["four", "one"]
  20 => ["two", "three"]

```

perhaps

---

<div class="post-metadata">

**Author:** ![Orr\_Orovan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/orr_orovan/32/15538_2.png) [@Orr\_Orovan](https://discourse.julialang.org/u/Orr_Orovan)\
**Post date:** [July 2, 2020, 1:18am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/3 "2020-07-02T01:18:43Z")

</div>

This works perfectly!

Thank you for the good help.

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [July 2, 2020, 5:25am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/4 "2020-07-02T05:25:46Z")

</div>

You are using the following signature for `get!`

```julia
get!(f::Function, collection, key)
...
This is intended to be called using `do` block syntax:

get!(dict, key) do
    # default value calculated here
    time()
end

```

Could you please explain the example: isn’t `get!` missing a parameter? Why `time()`? Could you also give an example of the use of `get!` in the do-block?

---

<div class="post-metadata">

**Author:** ![Wen-Wei\_Tseng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wen-wei_tseng/32/28839_2.png) [@Wen-Wei\_Tseng](https://discourse.julialang.org/u/Wen-Wei_Tseng)\
**Post date:** [July 2, 2020, 5:45am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/5 "2020-07-02T05:45:57Z")

</div>

**Edit** : Thank you @kristoffer.carlsson for pointing out my oversight and the code is working now.

```julia
# I forgot the `( )`. Fixed now
dict = Dict{Any, Any}()

# The doc example
get!(dict, :a) do
    time()
end

# The equivalent
get!( ()-> time(), dict, :b)

# If you already have function
function f()
    return time()
end

get!(f, dict, :c)

println(duct) # Dict{Any,Any}(:a => 1.593679792519603e9,:b => 1.59367979306765e9,:c => 1.59367992264622e9)

```

_My original post:_

AFAIK,

1. `do` block in Julia replaces the first parameter (`f::Function`) of `get!()`. Use `do` block if the function is more than a one-liner, for readability.
2. `time()` is to give a value to each element in `dict`. It can be anything as you see fit.

So it is equivalent to

```julia
get!(x-> time(), dict, key)

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 2, 2020, 8:25am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/6 "2020-07-02T08:25:10Z")

</div>

> [@Wen-Wei\_Tseng](#):
>
> `dict = Dict{Any, typeof(time())}`

You want to end that with a `()` to create an instance, and not just refer to the type.

---

<div class="post-metadata">

**Author:** ![Wen-Wei\_Tseng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wen-wei_tseng/32/28839_2.png) [@Wen-Wei\_Tseng](https://discourse.julialang.org/u/Wen-Wei_Tseng)\
**Post date:** [July 2, 2020, 8:46am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/7 "2020-07-02T08:46:25Z")

</div>

Thank you. That was my oversight. The code is working perfectly now.

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [July 2, 2020, 9:08am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/8 "2020-07-02T09:08:39Z")

</div>

I opened a [PR](https://github.com/JuliaLang/julia/pull/36511) with your clarification to the docs.

---

<div class="post-metadata">

**Author:** ![davidavdav](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidavdav/32/1065_2.png) [@davidavdav](https://discourse.julialang.org/u/davidavdav)\
**Post date:** [August 10, 2022, 3:17pm UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/9 "2022-08-10T15:17:24Z")

</div>

Often I have a one-to-one mapping, and then I define for myself

```julia
Base.inv(dict::Dict) = Dict(value => key for (key, value) in dict)

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 11, 2022, 3:40am UTC](https://discourse.julialang.org/t/dictionary-inverse-and-consolidating/42378/10 "2022-08-11T03:40:58Z")

</div>

Using SplitApplyCombine’s `group` we get some inverted dictionary similar to the solution above, but not as good as type is `Any`.  
Can it be improved?

```julia
using SplitApplyCombine

my_dict = Dict("one" => 10, "two" => 20, "three" => 20, "four" => 10, "five" => 30)

inverted = group(k -> my_dict[k], keys(my_dict))

3-element Dictionaries.Dictionary{Any, Vector{String}}
 20 │ ["two", "three"]
 10 │ ["four", "one"]
 30 │ ["five"]

```
