混合型の辞書 (int、float、string、numpy.arrays を含む) で比較できるようにしたいと考えています。私の最小限の例には辞書のリストがあり、関数 (またはジェネレーター) でそのリストを反復処理し、その関数 (またはジェネレーター) への **kwargs 入力で指定されたキーと値のペアを含む要素 (辞書) を選択したいと考えています。 )。
import re
list_of_dicts = [{'s1':'abcd', 's2':'ABC', 'i':42, 'f':4.2},
{'s2':'xyz', 'i':84, 'f':8.4}]
def find_list_element(**kwargs):
for s in list_of_dicts:
for criterion, criterion_val in kwargs.iteritems():
if type(criterion_val) is str:
if re.match(criterion_val, s.get(criterion, 'unlikely_return_val')):
yield s
continue
if s.get(criterion, None) == criterion_val:
yield s
print [a for a in find_list_element(i=41)] # []
print [a for a in find_list_element(i=42)] # [{'i': 42, 's2': 'ABC', 's1': 'abcd', 'f': 4.2}]
print [a for a in find_list_element(s1='xyz')] # []
print [a for a in find_list_element(s2='xyz')] # [{'i': 84, 's2': 'xyz', 'f': 8.4}]
print [a for a in find_list_element(s2='[a-z]')] # [{'i': 84, 's2': 'xyz', 'f': 8.4}]
上記の2つの問題は次のとおりです。
関数が文字列である比較を要求する場合、単純な文字列比較の代わりに正規表現一致 (re.search または re.match) に切り替えたいと思います。上記のコードでは、これは悪意のある型チェックによって実現されており、それほどエレガントには見えません。型チェックを含まないより良い解決策はありますか? それとも、これは Python で型チェックが許可されている場合ですか?
**kwargs
もちろん、複数の比較を含めることができます。現在、いくつかのフラグを含むソリューションしか考えられません (found = False
に切り替えられ、found = True
の各反復の最後に評価されますlist_of_dicts
)。それを生成するかどうかを決定する前に、各 s の比較結果を蓄積する賢い方法はありますか?
この辞書のコレクション全体をよりきれいにする方法はありますか?
PS: これの実際の使用例には、取得した MRI データセット (BRUKER) の表現が含まれます。データセットは、スキャンを表すオブジェクトの一部である dict に変換したパラメーター ファイルによって特徴付けられます。これらのデータセットを収集していますが、これらのパラメーター ファイルによって指定された特定の基準に基づいてさらにフィルター処理したいと考えています。これらのパラメーターは、文字列、数値、およびその他のあまり便利でない型にすることができます。
更新と蒸留された回答
@BrenBarnと@srgergによる入力から得られたコンセンサス回答を考え出すとしたら、これになります
list_of_dicts = [{'s1':'abcd', 's2':'ABC', 'i':42, 'f':4.2},
{'s2':'xyz', 'i':84, 'f':8.4}]
# just making up some comparison strategies
def regex_comp(a,b): return re.match(a,b)
def int_comp(a,b): return a==b
def float_comp(a,b): return round(a,-1) == round (b,-1)
pre_specified_comp_dict = {frozenset(['s1','s2']) : regex_comp,
frozenset(['i']): int_comp,
frozenset(['f']): float_comp}
def fle_new(**kwargs):
chosen_comps={}
for key in kwargs.keys():
# remember, the keys here are frozensets
cand_comp = [x for x in pre_specified_comp_dict if key in x]
chosen_comps[key] = pre_specified_comp_dict[cand_comp[0]]
matches = lambda d: all(k in d and chosen_comps[k](v, d[k])
for k, v in kwargs.items())
return filter(matches, list_of_dicts)
ここでの唯一の課題は、pre_specified_comp_dict
.