我有一个元组列表,一些元组有'start'和'end'作为元组中的第一项。我想将元组列表打包到一个元组列表列表中,其中子列表按其是否位于第一个项目中带有“开始”和第一个项目中的“结束”的元组之间进行分组。
list = [('start',1),('item_1',4),('item_2',2),('end',1),('start',10),('item_1',5),('item_3',2),('end',1),('start',10),('item_1',5),('item_3',2),('item_3',9),('end',1)]]
desired_result = [[('start',1),('item_1',4),('item_2',2),('end',1)],[('start',10),('item_1',5),('item_3',2),('end',1)],[('start',10),('item_1',5),('item_3',9),('item_3',2),('end',1)]]
我正在尝试使用groupby和itemgetter但收效甚微:
from operator import itemgetter
from itertools import groupby
[list(group) for key, group in itertools.groupby(sorted(list), itemgetter('start','end')]
答案 0 :(得分:1)
无需额外的模块。
我认为"结束"接下来是"开始",所以不需要寻找"结束"。
只需计算包含"start"
indexes = [i for i,e in enumerate(lst) if e[0]=='start']
然后使用切片创建子列表,使用特殊情况为最后一个元素包含最后一个列表
result = [lst[indexes[i]:indexes[i+1] if i<len(indexes)-1 else len(lst)] for i in range(len(indexes))]
结果:
[[('start', 1), ('item_1', 4), ('item_2', 2), ('end', 1)], [('start', 10), ('item_1', 5), ('item_3', 2), ('end', 1)], [('start', 10), ('item_1', 5), ('item_3', 2), ('item_3', 9), ('end', 1)]]
除{item 1}之外的desired_result
,但我尊重原始列表顺序,因此必须是预期结果中的拼写错误
答案 1 :(得分:1)
使用enumerate
,zip
和iter
函数的解决方案:
list1 = [('start',1),('item_1',4),('item_2',2),('end',1),('start',10),('item_1',5),('item_3',2),('end',1),('start',10),('item_1',5),('item_3',2),('item_3',9),('end',1)]
grouped_list = [list1[r[0]:r[1]+1]
for r in list(zip(*[iter([k for k,t in enumerate(list1)
if t[0] in ('start','end')])] * 2))]
print(grouped_list)
输出:
[[('start', 1), ('item_1', 4), ('item_2', 2), ('end', 1)], [('start', 10), ('item_1', 5), ('item_3', 2), ('end', 1)], [('start', 10), ('item_1', 5), ('item_3', 2), ('item_3', 9), ('end', 1)]]
详细:
zip(*[iter(sequence)] * n))
将从迭代器中提取一个项目(显示为iter(sequence)
)并生成一个包含start
到end
索引的2个项目的元组(连续)
list1[r[0]:r[1]+1]
会为每个start
- end
边界范围获取一小部分内容
答案 2 :(得分:0)
itertools.groupby
是一个排序功能。它不会帮助你。可能最好的方法是手动完成:
new_list = []
for item in old_list:
if item[0] == 'start':
new_list.append([item])
else:
new_list[-1].append(item)
请注意,如果第一个元组不是启动器,则会出错。它也将忽略结束点,因此任何不在开始和结束之间的元组将被添加到与最后一个结尾相同的列表中。如果你想抓住可能存在的所有问题,那就有点复杂了:
new_list = []
in_list = False
for item in old_list:
if item[0] == 'start':
if in_list:
raise ValueError("The last list hasn't completed yet.")
new_list.append([item])
in_list = True
else:
if item[0] == 'end':
if not in_list:
raise ValueError("The list has already completed.")
in_list = False
# If this is a problem, it will throw its own error
new_list[-1].append(item)