Alexander Senier
Alexander Senier

Reputation: 185

Get value of dict key without iterating items

I have a dict where the keys are of a class type. The __eq__ method of this class is implemented such that some of the class elements are ignored during comparison:

class ID:
    def __init__(self, name, location):
        self.name = name
        self.location = location

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

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

I use the dict to find elements of this class, no matter what the value of the location element is:

types = {ID("foo", "<stdin>:2:5"): "some data", ID("bar", "<stdin>:10:5"): "other data"}
search = ID("foo", "<stdin>:11:5")
if search in types:
    print(f"duplicate entry {search.name}")

However, when I want the location value of the key stored in the dict, I need to iterate through the dict:

if search in types:
    print(f"duplicate entry {search.name}")
    r = [k for k, _ in types.items() if k == search][0]
    print(f"previous location: {r.location}")

Is there any better way to obtain the key object of a dict from another key (which is considered equal)?

Edit: I'm interested in Python 3 only.

Upvotes: 1

Views: 125

Answers (3)

rioV8
rioV8

Reputation: 28663

You can create a dict sub class that will find the duplicate key for you

class ID:
    def __init__(self, name, location):
        self.name = name
        self.location = location

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

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

class MyDict(dict):
  def getSimilarKey(self, key):
    for k in self.keys():
      if k == key:
        return k
    return None
  @classmethod
  def create(cls, d):
    tmp = cls()
    tmp.update(d)
    return tmp

types = MyDict.create({ID("foo", "<stdin>:2:5"): "some data", ID("bar", "<stdin>:10:5"): "other data"})
search = ID("foo", "<stdin>:11:5")
if search in types:
    print(f"duplicate entry {search.name}")
    print(f"previous location: {types.getSimilarKey(search).location}")

Upvotes: 0

Malo
Malo

Reputation: 1313

Have you tried to directly get the attribute with this piece of code ?

search.location

or

types[search].location

This will give you the value you are looking for.

Upvotes: 0

Dani Mesejo
Dani Mesejo

Reputation: 61910

You could store the key object as part of the values:

# store the value and key as a tuple 
lookup_types = {k: (k, v) for k, v in types.items()}
if search in lookup_types:
    print(f"duplicate entry {search.name}")
    r, _ = lookup_types[search]
    print(f"previous location: {r.location}")

Output

duplicate entry foo
previous location: <stdin>:2:5

Upvotes: 2

Related Questions