Using range as a dictionary index in Python

Is it possible to do something like:

r = {range(0, 100): 'foo', range(100, 200): 'bar'} print r[42] > 'foo' 

Therefore, I would like to use a numerical range as part of the dictionary index. To complicate things, I would also like to use multi-indices such as ('a', range(0,100)) . Thus, the concept must be ideally extensible for this. Any suggestions?

A similar question was asked as here , but I am interested in a comprehensive implementation, and not different approaches to this question.

+5
source share
7 answers

If you are on Python 3.x, you can use range as the key, but to get the value you will do something like this:

 In [33]: r = {range(0, 100): 'foo', range(100, 200): 'bar'} In [34]: { r[key] for key in r if 42 in key} Out[34]: {'foo'} 

The reason you cannot do this in Python2.x is because the range function in version 2.7 onwards returns a list and lists cannot be used as dictionary keys because they do not provide a valid __hash__ method.

+4
source

As an alternative approach, if you are trying to find values ​​associated with specific ranges, you can use the Python bisect built-in library as follows:

 import bisect def boundaries(num, breakpoints=[100, 200], result=['foo', 'bar']): i = bisect.bisect(breakpoints, num-1) return result[i] print boundaries(42) 

This will display:

 foo 
+3
source

You can use immutable data types as a key. So there are no listings.

But you can use tupel to determine the upper and lower boundaries.

 r = {(0,100): 'foo', (100,200): 'bar'} 

I would get the value 42 as follows:

 res = "" for (k1,k2) in r: if (k1 < 42 and k2 > 42): res = r[(k1,k2)] print(res) 

But I admit that you do not need a dictionary for this.

+2
source

If you have an easy way to calculate a range from a point, for example, if all ranges are of a fixed size, you can use:

 def getIndex(p): start = floor(p/100)*100 return (start, start+100) 

Then define a dict:

 r = {(0, 100): 'foo', (100, 200): 'bar'} 

and access:

 r[getIndex(42)] 

This method is effective as:

  • You do not have an element in the dict for each number in the range (this also allows you to have valid "keys" values)
  • you're not going to, although the whole dict is to find the value, getting the value of O (1)

In addition, your getIndex function can be more complex, for example, if your ranges are irregular in length, your getIndex function can binary search for a sorted list of range boundaries and return a range tuple, not more than O(1) but O(log(n)) not bad ...

+2
source

You can use this:

 r=dict(zip(range(100),["foo"]*100)) r2=dict(zip(range(100,200),["bar"]*100)) r.update(r2) 
0
source

You can do it in one line

 r = dict(zip(range(200),["foo"]*100+["bar"]*100)) 
0
source

You can use the list description to get the desired dictionary:

 d = dict([(i,'foo') for i in range(0, 100)] + [(i,'bar') for i in range(100, 200)]) print d 
0
source

Source: https://habr.com/ru/post/1242597/


All Articles