# Getting a specific item from a Set

**URL:** <https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786>\
**Category:** General Usage\
**Tags:** question, dictionary, set\
**Created:** [October 15, 2022, 7:25pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786 "2022-10-15T19:25:41Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [October 15, 2022, 7:25pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/1 "2022-10-15T19:25:41Z")

</div>

Hi,

I have a set filled with custom objects.  
How can I get a specific item from the set equal to another object?

For example, I have a set of points. Then, I add a new point pp1. If pp1 already exists in the set, I want a way to obtain the stored object. This is because the stored point is the one required and may have references elsewhere.

```julia
mutable struct Pt
    x::Float64
    y::Float64
end

Base.hash(p::Pt) = hash((p.x+p.y,))
Base.:(==)(p1::Pt, p2::Pt) = hash(p1)==hash(p2)

p1 = Pt(1,0)
p2 = Pt(2,0)
S = OrderedSet([p1, p2])

# a new point
pp1 = Pt(1,0)

# Since pp1 is equal to p1, how to get p1 from the set?

```

I got a solution for OrderedSets as follows, but I might be missing some standard procedure to do that.

```julia
using DataStructures

mutable struct Pt
    x::Float64
    y::Float64
end

Base.hash(p::Pt) = hash((p.x+p.y,))
Base.:(==)(p1::Pt, p2::Pt) = hash(p1)==hash(p2)

# function to get an item from a Set (based on the ht_keyindex function from DataStructures
function getitem(s::OrderedSet{K}, key) where K
    h = s.dict
    slots = h.slots
    sz = length(slots)
    iter = 0
    maxprobe = h.maxprobe
    index = Base.hashindex(key, sz)
    keys = h.keys

    @inbounds while iter <= maxprobe
        si = slots[index]
        si==0 && break # slot empty
        if si>0 && isequal(key, keys[si])
            return keys[si] # it returns the key instead of the index
        end

        index = (index & (sz-1)) + 1
        iter += 1
    end

    error("key not found")
end

p1 = Pt(1,0)
p2 = Pt(2,0)

S = OrderedSet([p1, p2])

# the objectid obtained from getitem(S,pp1) is the one from p1 (as desired)
@show objectid( getitem(S,pp1) ) == objectid(p1)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 15, 2022, 7:27pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/2 "2022-10-15T19:27:20Z")

</div>

> [@RaulDurand](#):
>
> ```julia
> # Since pp1 is equal to p1, how to get p1 from the set?
> 
> ```

`Pt` is immutable; there’s no difference bweteen `p1` and `pp1`, just use `pp1`

```julia
julia> struct Pt
           x::Float64
           y::Float64
       end

julia> pp1 = Pt(1,0)
Pt(1.0, 0.0)

julia> p1 = Pt(1,0)
Pt(1.0, 0.0)

# no program should be able to distinguish p1 and pp1
julia> objectid(pp1)
0xb7c8b5259ebb4388

julia> objectid(p1)
0xb7c8b5259ebb4388

```

---

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [October 15, 2022, 7:29pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/3 "2022-10-15T19:29:11Z")

</div>

Thanks for the answer. I just edited the question. Pt is intended to be mutable.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 15, 2022, 7:56pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/4 "2022-10-15T19:56:41Z")

</div>

you probably want to just use a custom search function

```julia
julia> Base.:(==)(a::Pt, b::Pt) = (a.x == b.x) && (a.y==b.y)

julia> p1 = Pt(1,0); p2 = Pt(2,0); pp1 = Pt(1,0);

julia> S = Set([p1, p2]);

julia> function setfindfirst(s, target)
           for v in s
               v==target && return v
           end
           return nothing
       end
setfindfirst (generic function with 1 method)

julia> p1_another = setfindfirst(S, pp1)
Pt(1.0, 0.0)

julia> p1_another.x = 10;

julia> S
Set{Pt} with 2 elements:
  Pt(10.0, 0.0)
  Pt(2.0, 0.0)

```

---

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [October 15, 2022, 8:03pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/5 "2022-10-15T20:03:33Z")

</div>

Thanks @jling. That’s why I implemented the getitem function based on the ht\_keyindex function from DataStructures, which performs, I believe, binary search or another kind of fast search.

I wonder if this functionality could be available in Julia’s set structures. It is not the first time I stumbled upon this problem.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 15, 2022, 8:05pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/6 "2022-10-15T20:05:36Z")

</div>

> [@RaulDurand](#):
>
> I wonder if this functionality could be available in Julia’s set structures. It is not the first time I stumbled upon this problem.

open an issue

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [October 15, 2022, 9:56pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/7 "2022-10-15T21:56:10Z")

</div>

`getkey`?

[https://docs.julialang.org/en/v1/base/collections/#Base.getkey](https://docs.julialang.org/en/v1/base/collections/#Base.getkey)

---

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [October 15, 2022, 11:06pm UTC](https://discourse.julialang.org/t/getting-a-specific-item-from-a-set/88786/8 "2022-10-15T23:06:55Z")

</div>

Thanks @cjdoris. getkey functions are defined for dictionaries and not for sets.  
However, each set instance has an internal dictionary, thus the following works:

```julia
using DataStructures

mutable struct Pt
    x::Float64
    y::Float64
end

Base.hash(p::Pt) = hash((p.x+p.y,))
Base.:(==)(p1::Pt, p2::Pt) = hash(p1)==hash(p2)

p1 = Pt(1,0)
p2 = Pt(2,0)
S = OrderedSet([p1, p2])

pp1 = Pt(1,0)
@show objectid( getkey(S.dict, pp1, nothing) ) == objectid(p1) # shows true

```
