Question: Typical case:

```
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return self.age == other.age

    def __hash__(self):
        return hash(self.age)

    def __repr__(self):
        return '<Person {}>'.format(self.name)

v1 = Person('tom', 18)
v2 = Person('mary', 22)
v3 = Person('mary2', 22)

person_set = {v1, v2, v3}
print(person_set)

```

Now I only knows the age of the element I want to find is 18. How to find its name? Etc how to get the a reference to the element "Person('tom', 18)" in the hash set?

I want to do this job in **O(1)** (C++'s std::unordered\_set::find can do. Basically, construct a object with any name Person('xxx', 18) and call std::unordered\_set::find. C# added a similar function HashSet.TryGetValue(T, T) at very recent version 4.7.2)

**For python, I understanding using dictionary can be a workaround. But I want to know if there is a direct solution, similar to C++'s std::unordered\_set::find?.** 

***I need O(1) solution instead of O(N) solution. Otherwise, hash set makes no sense.***

Thanks.

Answer: 
There is no way to do this in O(1). `set` is not intended for such operations, and will not consistently return a search element versus a contained element. The closest operation is [set intersection](https://docs.python.org/3/library/stdtypes.html#frozenset.intersection), which uses arbitrary order and may thus return either the search or result element.

```
class HashKV:
    """A key: value pair with hash/eq defined by key, similar to a ``dict`` pair"""
    def __init__(self, k, v): self.k, self.v = k, v
    def __hash__(self): return hash(self.k)
    def __eq__(self, other): return self.k == other.k
    def __repr__(self): return f'{self.k}: {self.v}'

# Search Key - value is a placeholder
search = {HashKV(1, '?')}
# Search First - Works
print(search & {HashKV(1, 1)})  # {1: 1}
# Search Last - Fails
print({HashKV(1, 1)} & search)  # {1: ?}
# Search First - Fails
print(search & {HashKV(1, 1), HashKV(2, 2)})  # {1: ?}
# Search Last - Fails
print({HashKV(1, 1), HashKV(2, 2)} & search)  # {1: ?}

```

At least in CPython, [set intersection returns elements from the shorter set](https://github.com/python/cpython/blob/master/Objects/setobject.c#L1201-L1221), i.e. the search set and not the searched set.

The appropriate data structure to map from a key to a value is `dict`.

```
>>> v1 = Person('tom', 18)
>>> v2 = Person('mary', 22)
>>> v3 = Person('mary2', 22)
>>> person_map = {v.age: v for v in (v1, v2, v3)}
>>> person_map[18].name
tom
>>> person_map[18].name = 'barry'
>>> person_map[18].name
barry

```
There's no direct equivalent because **to quickly retrieve a specific element, you need to already know it** -- to be able to calculate its hash code -- so you already have it, just check membership if you want to know if it's present. Neither is there sense to return an "iterator to it" which is what the C++ function does -- because the set is unordered, the notion of a position in it is meaningless. Finally, because C++ has manual memory management and everything is mutable in it, you may want to use that iterator to retrieve the stored object instead of an equivalent one that you've constucted -- this doesn't apply to Python, either.

---

To alter a stored element, since they need to be immutable, you need to delete the old one and insert a new one:

```
tom = Person('tom', 18)   # if you know the element exactly

person_set.remove(tom)
person_set.add(Person('tom', 18))

```

If you don't know the element exactly, your only option is to search all elements one by one using the usual (i.e. not set-specific) syntax like in a list by whatever criteria -- which will have *O(N)* complexity. Note that this may yield any number of results, including none.

```
[e for e in person_set if e.name == 'tom']

```