我有以下Python元组:
my_tuple = ( "key1", ("nested_key1", "nested_key2"), "key3")
我需要测试dict是否包含"key1"
,("nested_key1", "nested_key2")
或"key3"
中的所有元素。如果任何根元组的索引中的所有元素都匹配,那么如果其他索引中没有其他匹配,则算法应仅评估为True
。如果元组中没有指定其他键,则可以忽略这些键以进行匹配。
意思是......
这些应该返回True:
matching_dict_root = {"key1": 1}
matching_dict_nested = {"nested_key1": 2, "nested_key2": 3}
unspecified_keys_are_allowed = {"key1": 1, "99problems": 99}
这些应该是假的:
too_many = {"key1": 1, "nested_key1": 1, "nested_key2": 2}
also_wrong = {"key1": 1, "nested_key2": 1}
可以假设(对于我目前的情况,但一般的解决方案是最受欢迎的):
Python-3.6,Python-2.7也很有用,但不是必需的。如果可能的话(我认为是,并且我将自己踢),标准。库。仅
答案 0 :(得分:1)
所以喜欢:
sum( keys in D if not isinstance(keys, tuple)
else all( key in D for key in keys )
for keys in my_tuple ) == 1
sum( ) == 1
而不是any( )
的原因是:
如果其他索引中没有其他匹配项,则仅评估为True
这意味着my_tuple
中只应有一个True
的索引,其余索引必须为False
。
答案 1 :(得分:1)
让我疯了,但这里是......
要获得一个扁平的元组列表,我们使用Flatten (an irregular) list of lists中的辅助函数:
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):
yield from flatten(el)
else:
yield el
这将允许使用frozenset.isdisjoint()
针对展平列表的子列表测试无效的交叉点。
在扩展@DanD的有用解决方案之后,最终解决方案是:
def all_attributes_exist_with_null_intersection(iterable, d):
return sum((i in d if not isinstance(i, tuple) else (all(sub_i in d for sub_i in i)))
and frozenset(d.keys()).isdisjoint(flatten([x for x in i if x != i]))
for i in iterable) == 1
<强>试验:强>
sample_tuple = ("key1", ("nested_key1", "nested_key2"), "key3")
true_tests = [
{"key1": 1},
{"nested_key1": 2, "nested_key2": 3},
{"key1": 1, "99problems": 99}
]
false_tests = [
{"key1": 1, "nested_key1": 1, "nested_key2": 2},
{"key1": 1, "nested_key2": 1}
]
trues = [all_attributes_exist_with_null_intersection(sample_tuple, d) for d in true_tests]
falses = [all_attributes_exist_with_null_intersection(sample_tuple, d) for d in false_tests]
print("Trues:\n{trues}\n\nFalses:\n{falses}".format(
trues=trues,
falses=falses
)
<强>输出:强>
Trues:
[True, True, True]
Falses:
[False, False]
<强>注意事项:强>
yield from
需要Python 3.3