views:

97

answers:

5

Hi, I have a dictionary which has coordinate pairs as a keys: i.e.:

d = {(15,21): "value1", (7,45): "value2", (500,321): "value3",...}

Now I need to return a sub dictionary of the elements where the keys are within a certain range: for example: the range of (6:16, 20:46) should return the following dictionary: d = {(15,21): "Value1", (7,45): value2} if there was no other element in that range. Is there any predefined dictionary function to do that? ..or do you have any other suggestions?

Thx

+1  A: 

Here is one way to do it

d = {(15,21): "value1", (7,45): "value2", (500,321): "value3"}
x1, x2, y1, y2 = 6, 16, 20, 46 
dict((k,v) for k, v in d.iteritems() if x1<k[0]<x2 and y1<k[1]<y2)

(edited finally after understanding the question properly through comments)

dheerosaur
It is more efficient if you used generator expression instead of list comprehension. `dict((k,v) ... x<k[1]<y)` instead of `dict([(k,v) ... x<k[1]<y])`.
KennyTM
@KennyTM - edited. Thank you.
dheerosaur
Shouldn't that be `and` instead of `or`? Assuming the OP wants both values to be in the given range.
jellybean
Thank you! This looks very neat, however I'm not sure about the efficiency..My dictionaries are up to 25.000 elements and I have to look for the nearest neighor of each element within the search distance, so I have to do search for every element in the dict.. could you expand on the idea of using generators?
Matej
Either I am misunderstanding the OP's question, or this answer is confused. On the first outer iteration of the list comprehension, `x=6` and `y=16`. Then you start iterating over the dictionary, and `k[0]=15`. Your test asks whether 15 (an X coordinate) lies between 6 (an X coordinate) and 16 (a Y coordinate). Isn't the relevant question whether 15 lies between 6 and 20 (the two X coordinates)? Just wondering -- I might have misunderstood the OP's question.
FM
@FM: You understood the question correctly:xmin,ymin,xmax,ymax = 14,20,16,22d1 = dict([(k,v) for k, v in d.items() if xmin<k[0]<xmax and ymin<k[1]<ymax])
Matej
as to the performance issue: if len(dict) is just 10.000 and I need to find the closest neighbor to each point, that is 10.000 times 10.000 iterations - it takes 33.7 sek just to return the subdict of each point within the search distance
Matej
@Matej, I am not able to understand this requirement. What do you mean by closest neighbor to each point?
dheerosaur
@dheerosaur: each item in the dictionary represents a point in a plane coordinate system - keys are coordinate pairs, values are attributes. So, I need to find the nearest point to each point in the plane taking into account attribute values as well.
Matej
A: 

No, there is no predefined function to do that. You could probably use a list comprehension.

items = [ value for key, value in d.items() if key[0] in range(6,16) and key[1] in range(20, 46) ]
Sjoerd
A: 

it looks like you want range queries. for large and complex dicts, this might not be efficient.

you might want to have a look at this, you might have to modify some of your data though

http://packages.python.org/lupyne/examples.html

bronzebeard
A: 

In Python 3.x we have dictionary comprehensions which make this sort of thing easy to do and easy to read:

d = {(15,21): "value1", (7,45): "value2", (500,321): "value3",...}
d_in_range = {k: v for k, v in d if 6 < k[0] < 20 and 16 < k[1] < 46} 
Tendayi Mawushe
A: 

Python dictionaries are hash tables, which are not suitable for efficient range queries on large data sets. For efficient range queries, you need to store the data in some structure that keeps the keys sorted. If your data set is static (or at least changes infrequently), then a sorted list with binary search would work. Otherwise, you should really use a B-Tree or similar structure.

Nathan Davis