2016-11-23 52 views
2

我有一个元组列表,一些元组有'开始'和'结束'作为元组中的第一项。我想把元组列表分成一系列元组列表,其中的子列表按照它们是否位于第一项中的“开始”和第一项中的“结束”之间的元组进行分组。如何根据特定的文本标准对元组列表进行分组/分组?

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')] 

回答

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)]] 

这是desired_result除了项目顺序,但我尊重原来的列表顺序,以便在预期结果中出现错字

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) 
1

使用enumeratezipiter功能的解决方案:

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))的项目,使2项的元组这点从start指数来end(连续)

  • list1[r[0]:r[1]+1]将获得项目的每一个切片start - end界限范围

相关问题