I want to make a Python dictionary. I want values like 0.25, 0.30, 0.35 to be keys in this dictionary. The problems is that I have values like 0.264, 0.313, 0.367. I want this values to access the keys e.g. I want every value from 0.25(inclusive) to 0.30(exclusive) to access the value under the key 0.25. Any ideas how to do this? I think I've done that before somehow, but I have no ideas right now. Thanks in advance.
Asked
Active
Viewed 146 times
1
-
2So you are looking for a way to round float values down to the nearest multiple of `0.05`? – Martijn Pieters Jan 23 '14 at 15:26
-
Yes, that would be ok too. – Borut Flis Jan 23 '14 at 15:32
2 Answers
8
Create a subclass of dict
with adjusted __getitem__
, __setitem__
, __delitem__
, __contains__
, get()
, pop()
and update()
methods that round the key:
class RoundingDict(dict):
def _round(self, key):
return int(key * 20) / 20.0
def __contains__(self, key):
return super(RoundingDict, self).__contains__(self._round(key))
def __getitem__(self, key):
return super(RoundingDict, self).__getitem__(self._round(key))
def __setitem__(self, key, value):
super(RoundingDict, self).__setitem__(self._round(key), value)
def __delitem__(self, key):
super(RoundingDict, self).__delitem__(self._round(key))
def get(self, key, default=None):
return super(RoundingDict, self).get(self._round(key), default)
def pop(self, key, default=None):
return super(RoundingDict, self).pop(self._round(key), default)
def update(self, iterable):
try:
super(RoundingDict, self).update({
self._round(k): v for k, v in iterable.iteritems()})
except AttributeError:
super(RoundingDict, self).update((
(self._round(k), v) for k, v in iterable))
This floors any key down to the nearest 0.05
multiple when getting, setting or deleting individual keys, as well as when updating the dictionary with multiple keys:
>>> d = RoundingDict()
>>> d[0.346] = 'Foo'
>>> d[0.34]
'Foo'
>>> d[0.30]
'Foo'
>>> d[0.35]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 6, in __getitem__
KeyError: 0.35
>>> d.get(0.34)
'Foo'
>>> d.get(0.35, 'default')
'default'

Ashwini Chaudhary
- 244,495
- 58
- 464
- 504

Martijn Pieters
- 1,048,767
- 296
- 4,058
- 3,343
-
If you only want to handle missing keys when calling `get`, one can just define a `__missing__` method instead. – Steinar Lima Jan 23 '14 at 15:39
-
@SteinarLima: using `__missing__` is very different from calling `.get()`. – Martijn Pieters Jan 23 '14 at 15:39
-
If I read the [docs](http://docs.python.org/2/library/stdtypes.html#mapping-types-dict) correctly, `__missing__` will be called (if defined) when the key is not present. – Steinar Lima Jan 23 '14 at 15:42
-
1@SteinarLima `get` is more similar to: `if key in dict: return dict[key]` - thus avoids the `__getitem__` call that'd trigger the `__missing__`... – Jon Clements Jan 23 '14 at 15:44
-
1@SteinarLima: `__missing__` will only be called when calling `__getitem__` with a key not yet present. `get()` does gives you the option to *not* alter the dictionary when looking for a default. The usecases are very distinct. – Martijn Pieters Jan 23 '14 at 15:47
-
1@SteinarLima: In fact `dict.get()` **never** alters the dictionary, even when `__missing__` is set. The `default` value is always returned for missing keys (which defaults to `None`). – Martijn Pieters Jan 23 '14 at 15:48
1
What you need is to make a custom dictionary class where the __getitem__
method rounds down the value before calling the standard __getitem__
method.

neil
- 3,387
- 1
- 14
- 11
-
Indeed! That's what happens when you answer of the top of your head about something you've never tried. – neil Jan 23 '14 at 15:40