import json import re def get_original_order(data, parent_key=''): """获取原始字典中所有键的顺序""" order = [] for key, value in data.items(): current_key = f"{parent_key}.{key}" if parent_key else key order.append(current_key) if isinstance(value, dict): order.extend(get_original_order(value, current_key)) return order def reorganize_dict(data, original_order): """根据原始顺序重新组织字典""" def get_dict_by_path(d, path): parts = path.split('.') current = d for part in parts[:-1]: current = current[part] return current result = {} # 按原始顺序重建字典结构 for path in original_order: parts = path.split('.') current = result for i, part in enumerate(parts[:-1]): if part not in current: current[part] = {} current = current[part] # 获取原始字典中对应路径的值 try: source_dict = get_dict_by_path(data, path) current[parts[-1]] = source_dict[parts[-1]] except KeyError: # 如果键不存在(可能是被重命名的键),跳过 continue return result def generate_key_paths(data, parent_key='', good_list=None, seen=None): # 保存原始顺序 original_order = get_original_order(data) if good_list is None: good_list = [] if seen is None: seen = set() key_paths = [] grouped_paths = set() no_keys_added = True # Step 1: Collect keys that match the pattern pattern = re.compile(r'(.+)-\d+$') prefix_groups = {} other_keys = [] for key in list(data.keys()): clean_key = key.replace(" ", "") match = pattern.match(clean_key) if match: prefix = match.group(1) if prefix not in prefix_groups: prefix_groups[prefix] = [] prefix_groups[prefix].append(key) else: other_keys.append(key) # Step 2: Handle grouped keys for prefix, keys in prefix_groups.items(): current_prefix_path = f"{parent_key}.{prefix}" if parent_key else prefix if len(keys) > 1: grouped_paths.add(current_prefix_path) if prefix not in seen: good_list.append(prefix) seen.add(prefix) no_keys_added = False else: old_key = keys[0] new_key = prefix value = data[old_key] data[new_key] = value del data[old_key] key_path = f"{parent_key}.{new_key}" if parent_key else new_key key_paths.append(key_path) if prefix not in seen: good_list.append(prefix) seen.add(prefix) no_keys_added = False # Step 3: Handle other keys (递归处理其他键) for key in other_keys: value = data[key] current_key = f"{parent_key}.{key}" if parent_key else key if isinstance(value, dict): if value: sub_key_paths, _, sub_grouped_paths, sub_no_keys_added = generate_key_paths( value, current_key, good_list, seen ) key_paths.extend(sub_key_paths) grouped_paths.update(sub_grouped_paths) no_keys_added = no_keys_added and sub_no_keys_added else: clean_key = key.replace(" ", "") key_paths.append(current_key.replace(" ", "")) if clean_key not in seen: good_list.append(clean_key) seen.add(clean_key) no_keys_added = False else: clean_key = key.replace(" ", "") key_paths.append(current_key.replace(" ", "")) if clean_key not in seen: good_list.append(clean_key) seen.add(clean_key) no_keys_added = False # Step 4: 删除 key_paths 中包含在 grouped_paths 中的元素 key_paths = [path for path in key_paths if path not in grouped_paths] # 根据原始顺序重新组织字典 reorganized_data = reorganize_dict(data, original_order) data.clear() data.update(reorganized_data) return key_paths, good_list, grouped_paths, no_keys_added # 示例使用 data1 = { "采购需求": { "多媒体会议厅设备": { "LED屏显示设备": { "户内全彩LED屏(全彩高刷)": [], "发送盒": [], "LED显示屏控制系统": [], "视频处理器": [], "智能配电柜": [], "台式电脑": [], "控制桌(定制)": [] }, "LED显示屏施工材料、技术服务费、包装费": { "结构边框": [], "线材(按需)": [], "包装材料": [] }, "扩声系统": { "主扩全频专业音箱": [], "专业功放-1": [], "专业功放-2": [], "辅助专业音箱": [], "壁挂支架": [], "返听专业音箱": [], "返听专业功放": [], "超低频专业音箱": [], "音箱地插": [], "调音台": [], "音频处理器": [], "抑制器": [], "无线话筒": [], "话筒呼叫控制嵌入软件": [], "天线分配器-1": [], "话筒天线": [], "有源监听音箱": [], "电源时序器": [] }, "辅助材料": { "机柜": [], "音频连接线-1": [], "音频连接线-2": [], "音频连接线-3": [], "其它辅材(音箱线、电源线、网线、视频线等)": [] }, "会议座椅": { "会议座椅": [] }, "电动窗帘": { "电动窗帘系统": [] } }, "云平台及备课电脑": { "备课一体机电脑": [], "云平台管理软件": [], "教学互动应用软件": [] }, "办公桌椅": { "办公桌椅": [] }, "文件柜": { "文件柜": [] }, "体育运动器材": { "移动式标准篮球架(12座)": [] } } } key_paths, good_list, grouped_paths, no_keys_added = generate_key_paths(data1) print(json.dumps(data1,ensure_ascii=False,indent=4)) print(key_paths) print(grouped_paths)