从元组列表生成目标嵌套列表的代码问题排查
问题描述
我有一个元组列表,格式如下:
mylist = [(20, 'Start', '2008-10-10', 'TBS'),...,(20, 'End', '2008-11-09', 'NG'), (21, 'Start', '2008-12-10', 'TBS'),...,(21, 'End', '2008-12-15', 'G'), (22, 'Start', '2009-01-10', 'TBS'),...,(22, 'End', '2009-12-10', 'B'),..]
其中...表示每个ID(比如20、21、22)对应的其他无关元组,我只需要保留包含Start或End的元组。
我期望生成这样的嵌套列表:
[[20, 'Start', '2008-10-10', 'End', '2008-11-09', 'NG'] , [21, 'Start', '2008-12-10', 'End', '2008-12-15', 'G'], [22, 'Start', '2009-01-10', 'End', '2009-12-10', 'B']]
我写了下面的代码:
code = 0 brr = [] for row in myList: if row[1] == "Start": arr = [] code = row[0] arr.append([row[0], row[1], row[2]]) continue if row[0] == code and row[1] == "End": arr.append([row[1], row[2], row[3]]) brr.append(arr) for k in brr: print(k)
但运行后结果结构错误还有重复项,输出如下:
[[[20, 'Start', '2008-10-10', 'End'], ['2008-11-09', 'NG']] , [[20, 'Start', '2008-10-10', 'End'], ['2008-11-09', 'NG']] , [[20, 'Start', '2008-10-10', 'End'], ['2008-11-09', 'NG']] , [[21, 'Start', '2008-12-10', 'End'], ['2008-12-15', 'G']], [[21, 'Start', '2008-12-10', 'End'], ['2008-12-15', 'G']], [[22, 'Start', '2009-01-10', 'End'], ['2009-12-10', 'B']]]
请问该怎么修正代码得到目标结果?
修正方案
咱们先拆解下你现有代码的问题:
- 嵌套层级不对:你在
arr里追加的是子列表(比如arr.append([row[0], row[1], row[2]])),导致最终结果多了一层嵌套,而目标是把所有元素放在同一个一维列表里。 - 重复添加问题:每次遇到
End就把arr塞进brr,但如果同一个ID的后续无关元组还会触发匹配(或者code没及时重置),就会重复添加相同的内容。
这里给你两种实用的修正思路,你可以根据自己的场景选择:
方法一:按ID分组后合并(更稳健)
先把所有Start和End元组过滤出来,再按ID分组存储信息,最后合并成目标格式:
# 第一步:过滤出只包含Start或End的元组,去掉无关数据 filtered_rows = [row for row in mylist if row[1] in ('Start', 'End')] # 第二步:用字典按ID分组,存储每个ID的Start和End信息 id_info = {} for row in filtered_rows: id_num = row[0] if id_num not in id_info: id_info[id_num] = {} if row[1] == 'Start': # 记录Start的类型和日期 id_info[id_num]['start'] = (row[1], row[2]) elif row[1] == 'End': # 记录End的类型、日期和最后一个字段 id_info[id_num]['end'] = (row[1], row[2], row[3]) # 第三步:生成目标格式的列表,按ID排序保证顺序 result = [] for id_num in sorted(id_info.keys()): info = id_info[id_num] # 按顺序拼接元素:ID + Start信息 + End信息 combined_list = [id_num] + list(info['start']) + list(info['end']) result.append(combined_list) print(result)
方法二:遍历过程中直接配对(更高效)
如果你的原始列表里,每个ID的Start元组一定出现在End元组之前,可以直接在遍历过程中完成配对,修正你原来的代码逻辑:
brr = [] current_group = None # 存储当前正在处理的ID的Start信息 for row in mylist: if row[1] == 'Start': # 遇到Start,初始化当前列表,直接存元素而非子列表 current_group = [row[0], row[1], row[2]] elif row[1] == 'End' and current_group is not None and row[0] == current_group[0]: # 匹配到对应ID的End,直接追加元素 current_group.extend([row[1], row[2], row[3]]) # 把完成的组加入结果,然后重置current_group避免重复添加 brr.append(current_group) current_group = None print(brr)
这两种方法都能生成你想要的目标结构,而且不会出现重复项。第一种方法不依赖元组的顺序,适合各种情况;第二种方法更轻量化,适合列表顺序固定的场景。
内容的提问来源于stack exchange,提问作者user9831231
相关产品推荐
相关产品推荐

