0

I have a dictionary with following

check = RangeDict({{
range(10, 100): 40,
range(110, 115): 40,
range(118, 121): 50,
range(130, 131): 50,
range(140, 141): 30
}

and I access the value with the following

class RangeDict(dict):
    def __getitem__(self, item):
        if not isinstance(item, range):  
            for key in self:
                if item in key:
                    return self[key]
            raise KeyError(item)
        else:
             return super().__getitem__(item)  

id =  199
print(check[id])

I need my dictionary to also include

{
range(10, 100): 40,
range(110, 115): 40,
range(118, 121): 50,
range(130, 131): 50,
range(140, 141): 30,
"a100": 110,
"c120": 100
}

Is this possible if using range for the integers and to also include string: values and how can I change function to read string

RecursionError: maximum recursion depth exceeded while calling a Python object

lunbox
  • 331
  • 3
  • 11
  • 3
    The keys of a dictionary do not all have to be the same type. – Scott Hunter Oct 27 '21 at 12:26
  • How can I return the string value if the key does not include range? – lunbox Oct 27 '21 at 12:38
  • 2
    Can you perhaps clarify what you are trying to do? The point of dictionaries is *direct* access to keys/values. Scanning through all keys to find which one matches the ``item`` defeats that point. – MisterMiyagi Oct 27 '21 at 12:41
  • "I access the value with the following" The code as shown is unsuitable to return anything. Once the loop has picked an appropriate ``key`` ``range``, the ``return self[key]`` will recurse and hit the bogus ``return RangeDict.values()``. Even fixing this to ``return self.values()`` or similar just returns *all* values for *all* keys. Can you please [edit] your question to show code that is feasible for what you claim it does, and reproduces the error you get later on? The [mre] help page should be useful. – MisterMiyagi Oct 27 '21 at 12:46
  • You should use `UserDict` for subclassing: https://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict-and-override-getitem-setitem – Tzane Oct 27 '21 at 12:56
  • I think things will be much simpler if you keep your dictionary keys as simple strings -- can you show/explain why you must use a range as a key? Just because dictionary keys _can_ be any immutable data type, that doesn't mean it's a good idea, especially if a simpler alternative would work. – Everett Oct 27 '21 at 13:00
  • I think OP is working from this code: https://stackoverflow.com/a/39358140/14536215 – Tzane Oct 27 '21 at 13:02
  • The range of keys go up to the 80000's so not sure sure what other approach I can use plus it also includes strings eg.a22200 – lunbox Oct 27 '21 at 13:02
  • 1
    Test ``if isinstance(item, int):`` instead of ``if not isinstance(item, range):``. – MisterMiyagi Oct 27 '21 at 13:04
  • That works thank you. Would people think there is a better apporach to this. The concern is there is a huge range of numbers to be included. – lunbox Oct 27 '21 at 13:07
  • 1
    If the ``range``s are not overlapping and may be sorted (i.e. you don't need insertion order), you can have a *much* better lookup speed by using binary search or a trie. But how best to do that is rather hard to say from such a small example. – MisterMiyagi Oct 27 '21 at 13:11

1 Answers1

-1

Just,

check = {
range(10, 100): 40,
range(110, 115): 40,
range(118, 121): 50,
range(130, 131): 50,
range(140, 141): 30,
"a100": 110,
"c120": 100
}

This is stored as :

{range(10, 100): 40,
 range(110, 115): 40,
 range(118, 121): 50,
 range(130, 131): 50,
 range(140, 141): 30,
 'a100': 110,
 'c120': 100}

And then to access,

a = check[range(10,100)]

Which gives:

40
  • 1
    This won't work for the desired in-range access, such as ``check[113]`` evaluating to ``40`` because ``113`` is in ``range(110, 115)``. – MisterMiyagi Oct 27 '21 at 14:31
  • Well, if you just want to add range, just do it with a for loop. Like: for i in range(10, 100): check[i] = 40. Next time be more clear with your problems. – mutedspeaker Oct 27 '21 at 14:38