Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Index python dict by object or two floats

I have a number of objects which I need to link to an integer number. These objects are ArcGIS Point objects (exactly what they are isn't relevant), which store an X and a Y value for a point, as floating point numbers.

I need to record that, for example:

Point(X = 2.765, Y = 3.982) -> 2
Point(X = 33.9, Y = 98.45) -> 7
Point(X = 1.23, Y = 2.43) -> 9
Point(X = 8.342, Y = 6.754) -> 5

I then need to be able to look up the resulting value by the X and Y values. I've tried using the Point objects as the dictionary's key, but this doesn't work as when I recreate the point object from the X and Y values it doesn't look it up properly anymore (presumably because the object ID has changed).

How should I go about linking these point values to the integers. Is there another way that I can use a dictionary?

like image 740
robintw Avatar asked Jan 21 '11 19:01

robintw


2 Answers

Add a hash method to your Point class:

...
def __hash__(self):
    return hash(self.x) ^ hash(self.y)
...

In other words, the hash of a point is a munging of the hash of the x and y coordinates.

EDIT: a better hash function (based on comments here) is:

...
def __hash__(self):
    return hash((self.x, self.y))
...

Because Python hashes tuples in a way that hash((p,q)) does not equal hash((q,p)), this will avoid hash collisions for points symmetric about the diagonal.

Then, you can use your Point object as keys for dictionaries, put them in sets, etc.

like image 148
payne Avatar answered Nov 14 '22 22:11

payne


Python dictionary keys need to be immutable types.

You could use a tuple like (2.765, 3.982). As long as a tuple contains only immutable types, it can be used as a dictionary key.

Here's my test in the console:

>>> my_dict[(12.3151, 1.2541)] = "test"
>>> my_dict[(12.3151, 1.2541)]
'test'

You could come up with a simple string convention like "2.765, 3.982" to turn a point into an index, but that would be a waste of processing. Also, a word of caution: If for some reason you choose to do this, you must use repr instead of str (here's a Stack Overflow post on that topic).

like image 35
Kyle Wild Avatar answered Nov 14 '22 21:11

Kyle Wild