如何避免嵌套for/if语句从嵌套列表和字典中提取数据?
优化monday.com API数据匹配的高效实现方案
需求说明
从monday.com API返回的嵌套结构数据中,找到与group标题第二个横杠(-)后内容完全匹配的item,获取该item的id并执行后续操作。例如:
- group标题:
123456-G123456.00 - 2000 Foo Bar: Mapping - 提取匹配目标:
2000 Foo Bar: Mapping - 匹配item的name字段,返回对应id:
1234564130
示例数据
{ 'data': { 'boards': [ { 'groups': [ { 'title': '123456-G123456.00 - 2000 Foo Bar: Mapping', 'items_page': { 'cursor': None, 'items': [ {'id': '1234564130', 'name': '2000 Foo Bar: Mapping'}, {'id': '1234564156', 'name': '2000.5 - 2000.5 Ground Model'} ] } }, { 'title': '123456-R12345.00 - Computer 2023', 'items_page': { 'cursor': None, 'items': [ {'id': '1234564074', 'name': 'Computer 2023'}, {'id': '1234564096', 'name': '3000.1 - 3000.1 Veggies'} ] } }, { 'title': '123456-T12345.00 - Dodge - Design', 'items_page': { 'cursor': None, 'items': [ {'id': '1234564028', 'name': 'Dodge - Design'}, {'id': '1234564048', 'name': '-'} ] } }, { 'title': 'Group Title', 'items_page': { 'cursor': None, 'items': [{'id': '1234563996', 'name': 'Task 1'}] } } ] } ] }, 'account_id': 123456 }
当前实现的问题
原代码采用多层嵌套for/if遍历字典键值对,存在以下问题:
- 代码冗余:遍历字典键来取值(如
for k,v in dictionary.items()),而非直接通过键名访问,增加不必要的逻辑 - 易出错:将item的键值转成列表后通过索引取值(
vals_list[1]),依赖键的顺序,若API返回结构变化会直接报错 - 时间复杂度高:多层嵌套导致接近O(n²)的时间复杂度,数据量大时效率低下
优化方案
方案1:层级直接访问+单次遍历(推荐,逻辑清晰)
直接按数据结构层级访问字段,避免无意义的键遍历,每个group和item仅遍历一次,时间复杂度降至O(n):
query_group_id = f""" {{ boards (ids: {my_board_id}) {{ groups {{ title items_page (limit: 50) {{ cursor items {{ id name }} }} }} }} }} """ data = {'query': query_group_id} r = requests.post(url=apiUrl, json=data, headers=headers) r_dict = r.json() group_board_info = r_dict['data']['boards'][0]['groups'] for group in group_board_info: # 提取group标题中第二个横杠后的内容,处理格式异常 title_parts = group['title'].split('-') if len(title_parts) < 3: continue # 标题格式不符合要求,跳过当前group target_name = '-'.join(title_parts[2:]).lstrip() # 遍历当前group下的items,匹配目标名称 for item in group['items_page']['items']: if item['name'] == target_name: create_subitem_for_item(item['id'], 'init') break # 每个group仅匹配一个item,找到后终止循环
方案2:构建映射字典(适合大数据量,查找更快)
先将所有item的name与id构建成映射字典,后续通过目标名称直接查找,查找操作时间复杂度为O(1):
query_group_id = f""" {{ boards (ids: {my_board_id}) {{ groups {{ title items_page (limit: 50) {{ cursor items {{ id name }} }} }} }} }} """ data = {'query': query_group_id} r = requests.post(url=apiUrl, json=data, headers=headers) r_dict = r.json() group_board_info = r_dict['data']['boards'][0]['groups'] # 构建item name到id的映射字典(注意:若存在重复name,后续item会覆盖前面的) item_name_to_id = {} for group in group_board_info: for item in group['items_page']['items']: item_name_to_id[item['name']] = item['id'] # 遍历group提取目标名称,查找对应id for group in group_board_info: title_parts = group['title'].split('-') if len(title_parts) < 3: continue target_name = '-'.join(title_parts[2:]).lstrip() if target_name in item_name_to_id: create_subitem_for_item(item_name_to_id[target_name], 'init')
优化点说明
- 直接键访问:替换原代码中遍历字典键的逻辑,直接用
group['title']、group['items_page']['items']等方式取值,代码更简洁 - 格式校验:增加标题分割后的长度判断,避免因标题格式不符合导致的报错
- 避免索引依赖:直接用
item['id']、item['name']访问字段,不依赖键的返回顺序 - 时间复杂度优化:两种方案均为O(n)时间复杂度,远优于原实现的O(n²)
内容的提问来源于stack exchange,提问作者Binx
相关产品推荐
相关产品推荐

