# Linking two values in either direction

**URL:** https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407
**Category:** General Usage
**Created:** [March 1, 2018, 5:28am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407 "2018-03-01T05:28:56Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 1, 2018, 5:28am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/1 "2018-03-01T05:28:56Z")

</div>

Hi all,

Is anyone aware of a type that can be used to link two values, in either direction? A trivial example would be if I wanted to link `"a"` to `:z`. I’d like to have some object `obj` such that `obj("a")` returns `:z`, and `obj(:z)` returns `"a"`.

I guess I could build this using a type that nests two dictionaries (one for each direction), or else using a `Vector{Tuple{T1, T2}}`, although both these options become a bit tricky if `T1` and `T2` are of the same type (i.e. linking `"a"`, and `"z"`). I thought it worth asking if there is already something pre-existing that solves this problem.

Cheers all,

Colin

---

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [March 1, 2018, 5:45am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/2 "2018-03-01T05:45:37Z")

</div>

One possible way to efficiently store multi key-values would be with `Set`.  
For example,

```julia
d = Tuple([:a,:b])
setdiff(d, [:a])

```

Each collection holds the key and all possible values. One can obtain the values by taking the key out. You can adapt this process in various ways such as a `Dict` which uses the key to find the `Set` and returns the `setdiff`.

---

<div class="post-metadata">

### Author: ![y4lu](https://avatars.discourse-cdn.com/v4/letter/y/47e85d/32.png) [@y4lu](https://discourse.julialang.org/u/y4lu)
#### Post date: [March 1, 2018, 5:57am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/3 "2018-03-01T05:57:11Z")

</div>

The simplest way would just be the flat file approach, you have an array of type Any(/etc) with two columns, pretty much like the `Vector{Tuple{T1, T2}}`, then find the one you want in one column (`find-x or .==`) and check the other column of that row.

It can get quite complicated/involved depending on what kind of link properties are needed

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [March 1, 2018, 8:03am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/4 "2018-03-01T08:03:51Z")

</div>

Sounds like a `Dict` would work:

```julia
julia> pairs = ["a" => :z, "foo" => :bar]
2-element Array{Pair{String,Symbol},1}:
 "a"=>:z
 "foo"=>:bar

julia> d = Dict(p for p in [pairs; reverse.(pairs)])
Dict{Any,Any} with 4 entries:
  :bar => "foo"
  :z => "a"
  "a" => :z
  "foo" => :bar

julia> d["a"]
:z

julia> d[:z]
"a"

```

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 1, 2018, 10:29am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/5 "2018-03-01T10:29:45Z")

</div>

Thanks for responding. Yes, that’s a neat way of doing things. After reading it, I was thinking of implementing something like this… until I saw DNF’s solution 🙂

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 1, 2018, 10:30am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/6 "2018-03-01T10:30:21Z")

</div>

Thanks for responding. Yes, my first instinct was to do something like this. But now that I’ve seen DNF’s solution, I think I’ll go with that.

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 1, 2018, 10:32am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/7 "2018-03-01T10:32:06Z")

</div>

I had no idea you could mix types in a Dict like that! That is awesome. I guess the downside is that every link is stored twice, but I think this is more than made up for by the simplicity of the solution.

Cheers and thanks, I’ll definitely be using this.

Colin

---

<div class="post-metadata">

### Author: ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)
#### Post date: [March 1, 2018, 2:58pm UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/8 "2018-03-01T14:58:39Z")

</div>

It wouldn’t work in all cases, however, depending on what you want. If both `"a"` and `"b`" maps to `:z` then the later one wins.

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 1, 2018, 10:21pm UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/9 "2018-03-01T22:21:35Z")

</div>

Yes agreed - to be totally robust, you’d need to check all existing pairs before adding a new one. But for my purposes it is more than sufficient.

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [March 2, 2018, 8:06am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/10 "2018-03-02T08:06:22Z")

</div>

> [@tk3369](#):
>
> It wouldn’t work in all cases, however, depending on what you want. If both “a” and “b” maps to :z then the later one wins.

not only - there could resist single links too. And who will wins depends on internal Dict order not on order in vector of pairs:

```julia
julia> ppairs = ["a" => :z, "foo" => :bar, :z=>"c"] # Julia 0.7 don't allow using pairs! :/ 
3-element Array{Pair{Any,Any},1}:
 Pair{Any,Any}("a", :z)    
 Pair{Any,Any}("foo", :bar)
 Pair{Any,Any}(:z, "c")    

julia> d = Dict(p for p in [ppairs; reverse.(ppairs)])
Dict{Any,Any} with 5 entries:
  "c" => :z # ("c", :z) is represented only with this direction
  :bar => "foo"
  :z => "a" # first pair won
  "a" => :z # first pair won
  "foo" => :bar

```

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 2, 2018, 9:21am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/11 "2018-03-02T09:21:38Z")

</div>

Interesting point.

FYI, pairs work just fine for me on v0.7. I’m on `Version 0.7.0-DEV.4379 (2018-02-24 23:50 UTC)`

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [March 2, 2018, 9:43am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/12 "2018-03-02T09:43:35Z")

</div>

Maybe it changed after your version?

```julia
julia> versioninfo()
Julia Version 0.7.0-DEV.4439
Commit cde00cf* (2018-03-01 17:22 UTC)
[...]

julia> pairs = ["a" => :z, "foo" => :bar, :z=>"c"]
ERROR: cannot assign variable Base.pairs from module Main

```

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [March 2, 2018, 9:54am UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/13 "2018-03-02T09:54:30Z")

</div>

Maybe… although various uses of pairs is mentioned quite a bit in the v0.7 release notes… it certainly doesn’t sound like the intention is to remove them.

I guess we’ll find out 🙂

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 2, 2018, 2:03pm UTC](https://discourse.julialang.org/t/linking-two-values-in-either-direction/9407/14 "2018-03-02T14:03:58Z")

</div>

Cf [this discussion about invertable dicts](https://discourse.julialang.org/t/invertable-dict-structure/7225). TL;DR: this is a useful datastructure, and it would be great if someone made a PR to [DataStructures.jl](https://github.com/JuliaCollections/DataStructures.jl) implementing it.
