2013-02-22 8 views
5

Mam następujący problem. Mając listę liczb całkowitych, chcę podzielić ją na listę list, gdy krok pomiędzy dwoma elementami pierwotnej listy wejściowej nie jest 1. Na przykład: input = [0, 1, 3, 5, 6, 7], wyjście = [[0, 1], [3], [5, 6, 7]]Python: podzielona lista liczb całkowitych w oparciu o krok między nimi

Napisałem następującą funkcję, ale jest to bzdura jak diabli i zastanawiałem się, czy ktokolwiek z was pomóż mi uzyskać lepsze rozwiązanie. Próbowałem użyć itertools, ale nie mogłem go rozwiązać.

Oto moje rozwiązanie:

def _get_parts(list_of_indices): 
    lv = list_of_indices 
    tuples = zip(lv[:-1], lv[1:]) 
    split_values = [] 
    for i in tuples: 
     if i[1] - i[0] != 1: 
      split_values.append(i[1]) 
    string = '/'.join([str(i) for i in lv]) 
    substrings = [] 
    for i in split_values: 
     part = string.split(str(i)) 
     substrings.append(part[0]) 
     string = string.lstrip(part[0]) 
    substrings.append(string) 
    result = [] 
    for i in substrings: 
     i = i.rstrip('/') 
     result.append([int(n) for n in i.split('/')]) 
    return result 

Thanks a lot!

Odpowiedz

7

To działa z każdym iterowalny

>>> from itertools import groupby, count 
>>> inp = [0, 1, 3, 5, 6, 7] 
>>> [list(g) for k, g in groupby(inp, key=lambda i,j=count(): i-next(j))] 
[[0, 1], [3], [5, 6, 7]] 
+4

Ładne rozwiązanie. Myślę, że opis będzie użyteczny: 'j = count()' tworzy licznik. Każde wywołanie 'next (j)' zwróci int kroku o 1. Nieoczywiste zachowanie python: wartość domyślna dla argumentu funkcji jest tworzona raz przy tworzeniu funkcji. Tak więc, 'j' zostanie zainicjalizowany za pomocą count() tylko raz, przy następnym wywołaniu' key', arg 'j' będzie miał wcześniej utworzone wystąpienie. 'groupby' doda do iterowalnego' g' wszystkich elementów z 'inp', które mają tę samą wartość klucza. Jeśli wartość klucza uległa zmianie - zostanie utworzone nowe g. Dla pozycji z inp: item = 0, key = 0-0 = 0; item = 1, key = 1-1 = 0; item = 3, key = 3-2 = 1; item = 5, key = 5-3 = 2 i tak dalej. – stalk

2
def _get_parts(i, step=1): 
    o = [] 
    for x in i: 
     if o and o[-1] and x - step == o[-1][-1]: 
      o[-1].append(x) 
     else: 
      o.append([x]) 
    return o 

_get_parts([0, 1, 3, 5, 6, 7], step=1) 
# [[0, 1], [3], [5, 6, 7]]) 
+0

Thanks a lot !!!!! – user1863555

0

Oto rozwiązanie z wykorzystaniem pętli for.

def splitbystep(alist): 
    newlist = [[alist[0]]] 
    for i in range(1,len(alist)): 
    if alist[i] - alist[i-1] == 1: 
     newlist[-1].append(alist[i]) 
    else: 
     newlist.append([alist[i]]) 
    return newlist 
0

To jak bym to zrobić:

inp = [0, 1, 3, 5, 6, 7] 
base = [] 

for item in inp: 
    if not base or item - base[-1][-1] != 1: # If base is empty (first item) or diff isn't 1 
     base.append([item])     # Append a new list containing just one item 
    else: 
     base[-1].append(item)    # Otherwise, add current item to the last stored list in base 
print base         # => [[0, 1], [3], [5, 6, 7]] 
Powiązane problemy