2016-09-01 25 views
6

Próbuję podzielić listę ciągów na listę krotek o nierównej długości zawierającą te ciągi, przy czym każda krotka zawiera ciągi początkowo oddzielone pustymi ciągami. Zasadniczo potrzebowałbym sparametryzowanego podziału, który mógłbym zastosować do list. Jeśli moja wstępna lista wygląda następująco:Podział listy na niejednolite krotki

init = ['a', 'b', '', 'c', 'd e', 'fgh', '', 'ij', '', '', 'k', 'l', ''] 

Ostatnim elementem tej listy jest zawsze zamykanie ''. Mogą być kolejno następujące '' s, które będą uważane za single. Rezultatem jest mi potrzebne:

end = [('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')] 

już mam brzydki kodu, który wykonuje pracę i dostaje się poza zasięgiem, gdy lista jest całkowicie wyszły:

end = [] 
while init[-1] == u'': 
init.pop() 
l = [] 
while init[-1] != u'': 
    l.append(init.pop()) 
end.append(tuple(l)) 

Chciałbym użyć listowych , ale bezskutecznie próbowałem rozpakowywać listy argumentów, odwracając listy z własnym odwołaniem, używając kolejki deque i różnych zapachów kodu, teraz wątpię, czy ma sens szukanie rozwiązania (zagnieżdżonego) ze zrozumieniem?

Odpowiedz

4

Można użyć itertools.groupby funkcję do grupy elementów na podstawie ich wielkości, jak to

>>> from itertools import groupby 
>>> init = ['a', 'b', '', 'c', 'd e', 'fgh', '', 'ij', '', '', 'k', 'l', ''] 
>>> [tuple(g) for valid, g in groupby(init, key=lambda x: len(x) != 0) if valid] 
[('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')] 

to zasadniczo grupy elementów na podstawie ich długości. Jeśli długość elementu nie jest równa zero, zostaną one umieszczone w grupie, dopóki element z innej grupy nie zostanie spełniony. Funkcja key zwróci True dla grupy elementów, których długość nie jest równa zero, w przeciwnym razie nie będzie równa False. Ignorujemy grupę za pomocą False (stąd sprawdzanie if valid).

+1

Czy to takie ładne zastąpić funkcję lambda z 'bool' rzucać ciąg i uzyskać podobny wynik? – Felix

4

Tutaj jest bardziej zwięzły i ogólne podejście z groupby jeśli chcesz podzielić swoją listę ze specjalnym separatorem:

>>> delimiter = '' 
>>> [tuple(g) for k, g in groupby(init, delimiter.__eq__) if not k] 
[('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')]