2009-08-02 16 views
8

Szukam wbudowanej funkcji Pythona (lub mechanizmu) do segmentowania listy na wymagane długości segmentów (bez mutowania listy wejściowej). Oto kod mam już:Segmentuj listę w Pythonie

>>> def split_list(list, seg_length): 
...  inlist = list[:] 
...  outlist = [] 
...  
...  while inlist: 
...   outlist.append(inlist[0:seg_length]) 
...   inlist[0:seg_length] = [] 
...  
...  return outlist 
... 
>>> alist = range(10) 
>>> split_list(alist, 3) 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 
+0

związane http://stackoverflow.com/questions/1915170/split-a-generator -terable-every-n-items-in-pyt hon-splitevery – jfs

Odpowiedz

17

Można użyć listowych:

>>> seg_length = 3 
>>> a = range(10) 
>>> [a[x:x+seg_length] for x in range(0,len(a),seg_length)] 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 
+4

Możesz również uczynić z niego generator, tj. (a [x: x + seg_length] dla x w zakresie (0, len (a), seg_length)), który będzie bardziej wydajny dla dużych sekwencji. – mhawke

+0

Ten jeden kod kreskowy jest tak zwięzły i użyteczny! –

2

nie to samo wyjście, ja nadal uważam, że grouper function jest pomocne:

from itertools import izip_longest 
def grouper(iterable, n, fillvalue=None): 
    args = [iter(iterable)] * n 
    return izip_longest(*args, fillvalue=fillvalue) 

dla python2 .4 i 2.5, które nie mają izip_longest:

from itertools import izip, chain, repeat 
def grouper(iterable, n, padvalue=None): 
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n) 

część kodu demo Wydajność:

alist = range(10) 
print list(grouper(alist, 3)) 

Wydajność: [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9 brak, brak) ]

4

Jak używać wyjścia? Jeśli tylko trzeba iteracyjne nad nim, jesteś lepiej tworząc iterable, który daje swoje grupy: Przykład

def split_by(sequence, length): 
    iterable = iter(sequence) 
    def yield_length(): 
     for i in xrange(length): 
      yield iterable.next() 
    while True: 
     res = list(yield_length()) 
     if not res: 
      return 
     yield res 

Zastosowanie:

>>> alist = range(10) 
>>> list(split_by(alist, 3)) 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 

ta wykorzystuje znacznie mniej pamięci niż próby skonstruowania cała lista w pamięci na raz, jeśli tylko pętli nad wynikiem, ponieważ tylko konstruuje jeden podzbiór naraz:

>>> for subset in split_by(alist, 3): 
...  print subset 
... 
[0, 1, 2] 
[3, 4, 5] 
[6, 7, 8] 
[9] 
+0

+1. Bardzo rozsądne podejście. Będę o tym pamiętać, jeśli moje dane wejściowe będą rosły. – kjfletch