def combine_and_update_results(original_data, updates): def normalize_key(key): """ 规范化键名: - 替换全角点号为半角点号。 - 删除所有空格(包括半角和全角)。 """ # 替换全角点号(.、。)为半角点号(.) key = key.replace('.', '.').replace('。', '.') # 删除所有空格(半角空格和全角空格) key = key.replace(' ', '').replace('\u3000', '') return key def normalize_original_data(d): """ 递归规范化原始数据字典的键。 """ if not isinstance(d, dict): return d normalized = {} for k, v in d.items(): nk = normalize_key(k) normalized[nk] = normalize_original_data(v) return normalized def normalize_update_value(value): """ 递归规范化更新字典中嵌套的字典的键。 """ if isinstance(value, dict): return {normalize_key(k): normalize_update_value(v) for k, v in value.items()} else: return value def recursive_update(data, key, value): """ 递归更新嵌套字典。 """ keys = key.split('.') for k in keys[:-1]: data = data.setdefault(k, {}) if isinstance(value, dict) and isinstance(data.get(keys[-1], None), dict): data[keys[-1]] = {**data.get(keys[-1], {}), **value} else: data[keys[-1]] = value # 1. 规范化原始数据字典的键 original_data = normalize_original_data(original_data) # 2. 规范化更新字典的键 normalized_updates = {} for key, value in updates.items(): nk = normalize_key(key) nv = normalize_update_value(value) normalized_updates[nk] = nv # 3. 执行递归更新 for key, value in normalized_updates.items(): recursive_update(original_data, key, value) return original_data # 测试用例1:复杂情况 def test_complex_case(): original_data = { 'user.name': 'Alice', 'user。details': { 'age': 30, 'address line': '123 Main St', # 全角空格 'preferences': { 'color': 'blue', 'food': 'sushi' } }, 'status': 'active', 'metrics': { 'score': 85, 'rank': 5 }, 'list_field': [1, 2, 3] } updates = { 'user. name': 'Bob', # 更新user.name 'user.details.age': 31, # 更新嵌套字段 'user.details.addressline': '456 Elm St', # 更新地址,键中有空格被移除 'user.details.preferences.hobby': 'cycling', # 添加新的嵌套字段 'status': 'inactive', # 更新顶级字段 'metrics.score': {'current': 90, 'max': 100}, # 更新为字典 'metrics.new_metric': 50, # 添加新的顶级嵌套字段 'new_field': 'new_value', # 添加新的顶级字段 'list_field': [4, 5] # 更新列表字段 } expected_result = { 'user': { 'name': 'Bob', 'details': { 'age': 31, 'addressline': '456 Elm St', 'preferences': { 'color': 'blue', 'food': 'sushi', 'hobby': 'cycling' } } }, 'status': 'inactive', 'metrics': { 'score': {'current': 90, 'max': 100}, 'rank': 5, 'new_metric': 50 }, 'list_field': [4, 5], 'new_field': 'new_value' } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试复杂情况失败。\n预期: {expected_result}\n实际: {result}" print("测试复杂情况通过。") # 测试用例2:更新为空 def test_empty_updates(): original_data = { 'key1': 'value1', 'key2': { 'subkey': 'subvalue' } } updates = {} expected_result = { 'key1': 'value1', 'key2': { 'subkey': 'subvalue' } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试更新为空失败。\n预期: {expected_result}\n实际: {result}" print("测试更新为空通过。") # 测试用例3:原始数据为空 def test_empty_original(): original_data = {} updates = { 'new.key': 'new value', 'nested。key.sub key': 123 } expected_result = { 'new.key': 'newvalue', 'nested.key': { 'subkey': 123 } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试原始数据为空失败。\n预期: {expected_result}\n实际: {result}" print("测试原始数据为空通过。") # 测试用例4:更新中包含非字典类型的值 def test_non_dict_values(): original_data = { 'a.b': { 'c.d': 1 }, 'list.field': [1, 2, 3] } updates = { 'a.b.c.d': {'new': 2}, 'list.field': 'not a list anymore' } expected_result = { 'a': { 'b': { 'c': { 'd': {'new': 2} } } }, 'list.field': 'not a list anymore' } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试更新中包含非字典类型的值失败。\n预期: {expected_result}\n实际: {result}" print("测试更新中包含非字典类型的值通过。") # 测试用例5:键中包含全角空格 def test_full_width_spaces(): original_data = { 'key with fullwidth spaces': 'value1', 'nested.key with.spaces': { 'sub key': 'subvalue' } } updates = { 'key with fullwidth spaces': 'updated_value', 'nested.key with spaces.new subkey': 'new_subvalue' } expected_result = { 'keywithfullwidthspaces': 'updated_value', 'nested': { 'keywithspaces': { 'subkey': 'new_subvalue' } } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试键中包含全角空格失败。\n预期: {expected_result}\n实际: {result}" print("测试键中包含全角空格通过。") # 测试用例6:复杂嵌套和不同数据类型 def test_nested_and_various_types(): original_data = { 'config.settings': { 'resolution': '1080p', 'volume': 75, 'controls': { 'jump': 'space', 'crouch': 'ctrl' } }, 'user.preferences': { 'theme': 'dark', 'notifications': True } } updates = { 'config.settings.resolution': '4K', 'config.settings.controls.run': 'shift', # 添加新控制 'config.settings.volume': 80, # 更新音量 'user.preferences.theme': 'light', # 更新主题 'user.preferences.language': 'en-US', # 添加新偏好 'new.section.setting': 'enabled' # 添加新部分 } expected_result = { 'config': { 'settings': { 'resolution': '4K', 'volume': 80, 'controls': { 'jump': 'space', 'crouch': 'ctrl', 'run': 'shift' } } }, 'user': { 'preferences': { 'theme': 'light', 'notifications': True, 'language': 'en-US' } }, 'new.section': { 'setting': 'enabled' } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试复杂嵌套和不同数据类型失败。\n预期: {expected_result}\n实际: {result}" print("测试复杂嵌套和不同数据类型通过。") # 测试用例7:键仅包含空格和点号 def test_keys_only_spaces_and_dots(): original_data = { '. ..': 'value1', '  ': 'value2', # 仅全角空格 'nested.key': { '.sub.key.': 'subvalue' } } updates = { '...': 'updated_value1', 'nested.key..sub.key.': 'updated_subvalue' } expected_result = { '..': 'updated_value1', '': 'value2', # 全角空格被删除后键为空字符串 'nested': { 'key': { 'subkey': 'updated_subvalue' } } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试键仅包含空格和点号失败。\n预期: {expected_result}\n实际: {result}" print("测试键仅包含空格和点号通过。") # 测试用例8:更新覆盖整个嵌套结构 def test_overwrite_nested_structure(): original_data = { 'settings': { 'display': { 'brightness': 70, 'contrast': 50 }, 'sound': { 'volume': 80 } } } updates = { 'settings.display': 'default', # 覆盖整个display字典 'settings.sound.volume': 90 # 更新音量 } expected_result = { 'settings': { 'display': 'default', 'sound': { 'volume': 90 } } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试覆盖整个嵌套结构失败。\n预期: {expected_result}\n实际: {result}" print("测试覆盖整个嵌套结构通过。") # 测试用例9:更新包含列表中的字典 def test_update_with_list_of_dicts(): original_data = { 'users': [ {'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25} ], 'settings': { 'theme': 'dark' } } updates = { 'users': [ {'name': 'Alice', 'age': 31}, # 更新第一个用户的年龄 {'name': 'Bob', 'age': 26}, # 更新第二个用户的年龄 {'name': 'Charlie', 'age': 22} # 添加新用户 ], 'settings.theme': 'light' # 更新主题 } expected_result = { 'users': [ {'name': 'Alice', 'age': 31}, {'name': 'Bob', 'age': 26}, {'name': 'Charlie', 'age': 22} ], 'settings': { 'theme': 'light' } } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试更新包含列表中的字典失败。\n预期: {expected_result}\n实际: {result}" print("测试更新包含列表中的字典通过。") # 测试用例10:键重复但规范化后不同 def test_duplicate_keys_after_normalization(): original_data = { 'key': { 'one':'value1', 'two':'value2' } } updates = { 'key.one': 'updated_value', 'keytwo': 'updated_value3' } expected_result = { 'keyone': 'updated_value', # 'key.one' 和 'key.one ' 规范化后合并为 'keyone' 'keytwo': 'updated_value3' # 'key two' 规范化后为 'keytwo' } result = combine_and_update_results(original_data, updates) assert result == expected_result, f"测试键重复但规范化后不同失败。\n预期: {expected_result}\n实际: {result}" print("测试键重复但规范化后不同通过。") # 主函数,运行所有测试用例 def run_all_tests(): test_functions = [ # test_complex_case, # test_empty_updates, # test_empty_original, # test_non_dict_values, # test_full_width_spaces, # test_nested_and_various_types, # test_keys_only_spaces_and_dots, # test_overwrite_nested_structure, # test_update_with_list_of_dicts, test_duplicate_keys_after_normalization ] for test_func in test_functions: try: test_func() except AssertionError as e: print(e) except Exception as ex: print(f"{test_func.__name__} 运行时发生错误: {ex}") print("所有测试用例已执行完毕。") if __name__ == '__main__': run_all_tests()