The dict dictionary is fast and very easy to use. If you want to search for a key with a regular expression, you would normally do this, but if you use it a lot, it's a hassle.
a = dict(abc=1, def=2) #-> {"abc": 1, "def": 2}
s = re.compile(".bc")
ret = []
for k in a:
if s.search(k):
ret.append(a[k])
print(ret) #-> [1]
#It looks like this at best even if it is shortened by the inclusion notation, but it is not readable and I do not know what I wanted to do when I read the source when I forgot.
s = re.compile(".bc")
[a[k] for k in a if s.search(k)] #-> [1]
Since this is troublesome, I extended the standard dict so that it can be used like this.
a = rdict(abc=1, def=2) #-> {"abc": 1, "def": 2}
a.search(".bc") #-> [1]
The source is like this.
import re
from functools import lru_cache
@lru_cache(16) # re.Since compile is a fairly heavy process, the same regular expression pattern is cached to gain performance.
def re_call(pattern, flags=0, call_re_func="search"):
return re.compile(pattern, flags=flags).__getattribute__(call_re_func)
class rdict(dict):
def _filter(self, _callable):
return (k for k in self if _callable(k))
def isin(self, key_or_function):
if callable(key_or_function):
return any(True for _ in self._filter(key_or_function))
return dict.__contains__(self, key_or_function)
def findall(self, key_or_function):
if callable(key_or_function):
return [dict.__getitem__(self, key) for key in self._filter(key_or_function)]
return dict.__getitem__(self, key_or_function)
def search(self, pattern, flags=0):
return [dict.__getitem__(self,key) for key in self if re_call(pattern, flags, "search")(key)]
def fullmatch(self, pattern, flags=0):
return [dict.__getitem__(self,key) for key in self if re_call(pattern, flags, "fullmatch")(key)]
def __setitem__(self, key_or_function, value):
if callable(key_or_function):
for key in self._filter(key_or_function):
dict.__setitem__(self, key, value)
else:
return dict.__setitem__(self, key_or_function, value)
def __delitem__(self, key_or_function):
if callable(key_or_function):
for key in list(self._filter(key_or_function)):
dict.__delitem__(self, key)
else:
return dict.__delitem__(self, key_or_function)
I've added some other functions, but here's an image of how to use them.
Find out if there is a matching key in the regular expression pattern
>>> a.isin(re.compile(".b.*").search)
True
>>> a.isin(re.compile(".z.*").search)
False
Other 1. Returns the value when having a key when the condition is true.
>>> a.findall(lambda x: len(x) == 3)
[1, 2]
Other 2. Search the key in the range and return the value If the argument of findall is callable, anything works, so the following applications are also possible
>>> from datetime import datetime
>>> b = funcdict()
>>> b[datetime(2020,1,1)] = "2020/01/01"
>>> b[datetime(2020,2,1)] = "2020/02/01"
>>> b[datetime(2020,3,1)] = "2020/03/01"
>>> def between_0131_0202(x):
... return datetime(2020,1,31) < x and x < datetime(2020,2,2)
>>> b.findall(between_0131_0202)
['2020/02/01']
>>> def less_0401(x):
... return x < datetime(2020, 4, 1)
>>> b.isin(less_0401)
True
>>> def grater_0401(x):
... return x > datetime(2020, 4, 1)
>>> b.isin(grater_0401)
False
>>> b.findall(less_0401)
['2020/01/01', '2020/02/01', '2020/03/01']
After that, the function to change the value of the key that matches the condition at once
>>> b[less_0401] = "test"
>>> b
{datetime.datetime(2020, 1, 1, 0, 0): 'test',
datetime.datetime(2020, 2, 1, 0, 0): 'test',
datetime.datetime(2020, 3, 1, 0, 0): 'test'}
By the way, the function to delete all the keys that match the conditions at once
>>> del b[between_0131_0202]
>>> b
{datetime.datetime(2020, 1, 1, 0, 0): 'test',
datetime.datetime(2020, 3, 1, 0, 0): 'test'}
Recommended Posts