2016-11-23 72 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界限範圍

相關問題