Quantcast
Channel: dictionaryタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 99

pythondict辞書キーを正規表現で検索する

$
0
0

dictキーを正規表現で検索したい

dict辞書は高速で非常に使い勝手が良い。
キーを正規表現で検索したい場合普通はこうすると思うが、多用する場合は面倒だ。

a=dict(abc=1,def=2)#-> {"abc": 1, "def": 2}
s=re.compile(".bc")ret=[]forkina:ifs.search(k):ret.append(a[k])print(ret)#-> [1]
# 内包表記で短くなってもせいぜいこんな感じだが、可読性が悪く、忘れたころにソースを読むと何をやりたかったのかよくわからん。
s=re.compile(".bc")[a[k]forkinaifs.search(k)]#-> [1]

これが面倒なので標準のdictを拡張してこんな感じで使えるようにしてみた。

a=rdict(abc=1,def=2)#-> {"abc": 1, "def": 2}
a.search(".bc")#-> [1]

ソースはこう。

importrefromfunctoolsimportlru_cache@lru_cache(16)# re.compileは結構重めな処理なので、同じ正規表現パターンはキャッシュし、性能稼ぐ
defre_call(pattern,flags=0,call_re_func="search"):returnre.compile(pattern,flags=flags).__getattribute__(call_re_func)classrdict(dict):def_filter(self,_callable):return(kforkinselfif_callable(k))defisin(self,key_or_function):ifcallable(key_or_function):returnany(Truefor_inself._filter(key_or_function))returndict.__contains__(self,key_or_function)deffindall(self,key_or_function):ifcallable(key_or_function):return[dict.__getitem__(self,key)forkeyinself._filter(key_or_function)]returndict.__getitem__(self,key_or_function)defsearch(self,pattern,flags=0):return[dict.__getitem__(self,key)forkeyinselfifre_call(pattern,flags,"search")(key)]deffullmatch(self,pattern,flags=0):return[dict.__getitem__(self,key)forkeyinselfifre_call(pattern,flags,"fullmatch")(key)]def__setitem__(self,key_or_function,value):ifcallable(key_or_function):forkeyinself._filter(key_or_function):dict.__setitem__(self,key,value)else:returndict.__setitem__(self,key_or_function,value)def__delitem__(self,key_or_function):ifcallable(key_or_function):forkeyinlist(self._filter(key_or_function)):dict.__delitem__(self,key)else:returndict.__delitem__(self,key_or_function)

その他にもいくつか関数を追加してるが使い方のイメージはこう。

正規表現パターンで一致するキーがあるかどうかを調べる

>>>a.isin(re.compile(".b.*").search)True>>>a.isin(re.compile(".z.*").search)False

その他1、条件が真になる場合のキーを持つ場合の値を返す

>>>a.findall(lambdax:len(x)==3)[1,2]

その他2、キーを範囲で検索し、値を返す
findallの引数はcallableなら、何でも動くので以下のような応用も可

>>>fromdatetimeimportdatetime>>>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">>>defbetween_0131_0202(x):...returndatetime(2020,1,31)<xandx<datetime(2020,2,2)>>>b.findall(between_0131_0202)['2020/02/01']>>>defless_0401(x):...returnx<datetime(2020,4,1)>>>b.isin(less_0401)True>>>defgrater_0401(x):...returnx>datetime(2020,4,1)>>>b.isin(grater_0401)False>>>b.findall(less_0401)['2020/01/01','2020/02/01','2020/03/01']

あとは、条件にマッチするキーの値を一括で変更する機能

>>>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'}

ついでに、条件にマッチするキーを一括で削除する機能

>>>delb[between_0131_0202]>>>b{datetime.datetime(2020,1,1,0,0):'test',datetime.datetime(2020,3,1,0,0):'test'}

Viewing all articles
Browse latest Browse all 99

Trending Articles