递归匹配关联ID,构建规则/量词/转换映射字典的技术求助
问题
现有一个包含rules、quantifiers(示例中对应quant键)、transformations(示例中对应trans键)的字典,各层级对象通过id关联,需完成以下操作:
- 给定
attr = [123, 456],先匹配quantifiers中id在attr内的项,获取其transIds; - 匹配
transformations中id在transIds内的项,获取其rules列表; - 匹配
rules中id在上述rules列表内的项,同时从这些项的logic中提取属于quantifiers的metrics值; - 最终返回格式为
{'rules':[...], 'quantifiers':[...], 'transformations':[...]}的字典。
用户尝试的代码因遍历顺序错误(先遍历rules时,trans和rules列表为空)无法正确捕获关联数据,示例字典与尝试代码如下:
示例字典:
test_dict = { 'rules': [ {'id': 123, 'logic': '{"$or":[{"$and":[{"baseOperator":null,"operator":"does_not_contain_ignore_case","operand1":"metrics.123","operand2":"metrics.456"}]}]}'}, {'id': 589, 'logic': '{"$or":[{"$and":[{"baseOperator":null,"operator":"does_not_contain_ignore_case","operand1":"metrics.123","operand2":0}, {"baseOperator":null,"operator":"does_not_contain_ignore_case","operand1":"metrics.456","operand2":0}]}]}'}, {'id': 51, 'logic': '{"$or":[{"$and":[{"baseOperator":null,"operator":"does_not_contain_ignore_case","operand1":"metrics.789","operand2":"metrics.1"}]}]}'}, ], 'quant': [ {'id':123, 'transIds': [1, 2, 3], 'qualifiedId': 'metrics.123'}, {'id':456, 'transIds': [1, 6], 'qualifiedId': 'metrics.456'}, {'id':789, 'transIds': [9], 'qualifiedId': 'metrics.789'} ], 'trans': [ {'id':1, 'rules': [123, 120]}, {'id':6, 'rules':[589, 2]} ] }
尝试的错误代码:
attr = [123, 456] keys = list(test_dict.keys()) trans = [] rules = [] for iter in range(len(keys)): for in_iter in range(len(test_dict[keys[iter]])): if test_dict[keys[iter]][in_iter].get('id') in attr: if test_dict[keys[iter]][in_iter].get('transIds') is not None: for J in test_dict[keys[iter]][in_iter].get('transIds'): trans.append(J) if test_dict[keys[iter]][in_iter].get('id') in trans: if test_dict[keys[iter]][in_iter].get('rules') is not None: for K in test_dict[keys[iter]][in_iter].get('rules'): rules.append(K) if test_dict[keys[iter]][in_iter].get('id') in rules: if test_dict[keys[iter]][in_iter].get('logic') is not None: print(test_dict[keys[iter]][in_iter].get('logic'))
解决方案
核心问题是原代码乱序遍历所有层级,没有按照需求的依赖顺序执行。正确的做法是按需求步骤依次执行,先获取quantifiers,再推导transformations,最后获取rules并提取metrics。
完整实现代码
import json def get_associated_data(test_dict, attr): # 步骤1:筛选目标quantifiers(对应示例中的quant),收集transIds target_quants = [q for q in test_dict['quant'] if q['id'] in attr] trans_ids = set() for q in target_quants: trans_ids.update(q.get('transIds', [])) # 步骤2:筛选目标transformations(对应示例中的trans),收集ruleIds target_trans = [t for t in test_dict['trans'] if t['id'] in trans_ids] rule_ids = set() for t in target_trans: rule_ids.update(t.get('rules', [])) # 步骤3:筛选目标rules,同时提取logic中的metrics对应的quantifiers target_rules = [r for r in test_dict['rules'] if r['id'] in rule_ids] # 建立quant的qualifiedId到对象的映射,方便快速查找 quant_map = {q['qualifiedId']: q for q in test_dict['quant']} # 收集所有从logic中提取到的有效quantifiers extracted_quants = set() for rule in target_rules: logic_json = json.loads(rule['logic']) # 递归遍历logic结构,提取所有metrics.xxx格式的operand值 def extract_metrics(obj): if isinstance(obj, dict): for k, v in obj.items(): if k in ['operand1', 'operand2'] and isinstance(v, str) and v.startswith('metrics.'): extracted_quants.add(v) else: extract_metrics(v) elif isinstance(obj, list): for item in obj: extract_metrics(item) extract_metrics(logic_json) # 把extracted_quants转换成对应的quant对象 final_quants = [quant_map[q_str] for q_str in extracted_quants if q_str in quant_map] # 合并初始的target_quants和提取到的quants,按id去重 quant_id_set = {q['id'] for q in target_quants + final_quants} final_quants = [q for q in test_dict['quant'] if q['id'] in quant_id_set] # 整理成要求的返回格式 return { 'rules': target_rules, 'quantifiers': final_quants, 'transformations': target_trans } # 测试调用 attr = [123, 456] result = get_associated_data(test_dict, attr) print(json.dumps(result, indent=2))
代码说明
- 按依赖顺序执行:严格按照需求步骤依次处理,先获取目标quantifiers,再推导关联的transformations,最后获取rules并提取metrics,避免了原代码乱序遍历导致的空列表问题。
- 用集合去重:使用
set存储trans_ids和rule_ids,避免重复添加同一id。 - 解析JSON逻辑字符串:将
logic字段的JSON字符串解析为字典,通过递归遍历提取所有metrics.xxx格式的操作数,再映射到对应的quantifiers对象。 - 去重最终quantifiers:合并初始筛选的quantifiers和从logic中提取的quantifiers,按id去重,确保结果无重复项。
运行结果
返回的字典中:
rules包含id为123、589的规则transformations包含id为1、6的转换项quantifiers包含id为123、456的量化项(与attr匹配且在logic中出现)
内容的提问来源于stack exchange,提问作者Dollar Tune-bill
相关产品推荐
相关产品推荐

