2013-02-22 10 views
5

Ho il seguente problema. Avendo una lista di interi, voglio dividerli, in una lista di liste, ogni volta che il passaggio tra due elementi della lista di input originale non è 1. Ad esempio: input = [0, 1, 3, 5, 6, 7], output = [[0, 1], [3], [5, 6, 7]]Python: elenco diviso di interi in base al passaggio tra di loro

Ho scritto la seguente funzione, ma è uggly come l'inferno, e mi chiedevo se qualcuno di voi ragazzi sarebbe aiutami a trovare una soluzione migliore. Ho provato ad usare itertools, ma non ho potuto risolverlo.

Ecco la mia soluzione:

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 

Grazie mille!

risposta

7

Questo funziona con qualsiasi iterabile

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

Bella soluzione. Penso che la descrizione sarà utile: 'j = count()' crea un contatore. Ogni chiamata a 'next (j)' ritornerà al punto int di 1. Comportamento non ovvio del pitone: il valore predefinito per l'argomento della funzione viene creato una volta alla creazione della funzione. Quindi, 'j' sarà inizializzato con count() solo una volta, alla prossima chiamata a' key', arg 'j' avrà istanza creata in precedenza. 'groupby' aggiungerà a iterable' g' tutti gli elementi da 'inp', che hanno lo stesso valore chiave. Se il valore della chiave è cambiato, viene creata una nuova g. Per elementi da 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 e così via. – 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

Grazie mille !!!!! – user1863555

0

Ecco una soluzione che utilizza un ciclo 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

Ecco come lo farei:

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