2012-04-12 21 views
12

Normalmente, vuoi andare al contrario, like here. Mi chiedevo come è possibile convertire un elenco piatta a un elenco di lista, quasy serie rimodellare in pythonconverti una lista piatta in lista di elenchi in python

In NumPy si potrebbe fare qualcosa di simile:

>>> a=numpy.aranage(9) 
>>> a.reshape(3,3) 
>>> a 
array([[0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8]]) 

mi chiedevo come si fa il contrario, e la mia solita soluzione è qualcosa del tipo:

>>> Mylist 
['a', 'b', 'c', 'd', 'e', 'f'] 
>>> newList = [] 
for i in range(0,len(Mylist),2): 
...  newList.append(Mylist[i], Mylist[i+1]) 
>>> newList 
[['a', 'b'], ['c', 'd'], ['e', 'f']] 

c'è un modo "Pythonico" per farlo?

+0

è meglio non usare 'list' come nome di variabile dato che c'è la funzione incorporata' list() ' – jamylak

+0

yeap hai ragione, stavo giusto modificando il codice velocemente, il mio codice originale non sembra quello. – Oz123

risposta

27
>>> l = ['a', 'b', 'c', 'd', 'e', 'f'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Come è stato sottolineato da @Lattyware, questo funziona solo se ci sono abbastanza elementi in ogni argomento della funzione zip ogni volta che restituisce una tupla. Se uno dei parametri ha meno voci degli altri, gli articoli sono tagliati ad es.

>>> l = ['a', 'b', 'c', 'd', 'e', 'f','g'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Se questo è il caso, allora è meglio usare la soluzione @Sven Marnach

How does zip(*[iter(s)]*n) work

+3

Questa soluzione funziona solo se ci sono abbastanza elementi per riempirla, altrimenti gli articoli vengono tagliati. –

+0

Creazione di un generatore quindi duplicazione di un riferimento ad esso; intelligente. –

+1

@NickT beh tecnicamente è un iteratore, non un generatore e non posso prendermi il merito dell'intelligenza :) – jamylak

11

Questo è solitamente fatto utilizzando la ricetta cernia dal itertools documentation:

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return itertools.izip_longest(fillvalue=fillvalue, *args) 

Esempio:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 
>>> list(grouper(2, my_list)) 
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', None)] 
0

Se si preferisce una lista di liste, piuttosto che una lista di tuple da una semplice lista, allora si potrebbe fare questo:

a = range(20) # sample starting list 
    b = [] # new list 
    c = [] # alternate new list 
    # ny is length of new list. nx length of each list within it 
    nx = 5; ny = 4 
    bb = 0; ee = bb + nx # option one: sliding indeces for slices. 
    for ii in range(ny-1): 
     bb += nx 
     ee += nx 
     b.append(a[bb:ee]) 
     c.append(a[slice(ii*nx,nx*(ii+1))]) # option two, use slice() 

(Ho giocato in giro con restringimento tutto il ciclo for in una sola riga con le liste di comprensione, ma non hanno avuto successo. il modo in cui l'ho usato, slice() può quasi farti arrivare lì.) Un possibile vantaggio di questi approcci rispetto agli altri menzionati è che se la tua lista originale, piatta non è un multiplo pari delle dimensioni del tuo nuovo, desiderato lista di liste, non perderete alcun dato. L'avvertenza è che l'ultima lista sarà più corta di tutte le altre, in quanto conterrà gli "avanzi". concesso, nessuno di questi metodi mi sembra molto pitonico.

+0

Non capisco perché stai usando 'slice()' nel secondo approccio, piuttosto che la sintassi dello slice. Fare un calcolo non significa che non puoi usare "a [ii * nx: nx * (ii + 1)]" o qualsiasi altra cosa. – Blckknght

5

altro modo per creare una lista di liste può essere semplificata come illustrato di seguito:

>>>MyList = ['a','b','c','d','e','f'] 
# Calculate desired row/col 
>>>row = 3 
>>>col = 2 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f']] 

Questo può metodo può essere esteso per produrre qualsiasi dimensione riga e colonna. Se si seleziona valori di riga e di colonna in modo che row*col >len(MyList), sottolista (riga) contenente l'ultimo valore MyList finirà qui, e NewList verrà semplicemente riempito con il numero appropriato di liste vuote soddisfare le esigenze riga/col

>>>MyList = ['a','b','c','d','e','f','g','h'] 
>>>row = 3 
>>>col = 3 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g','h']] 

>>>row = 4 
>>>col = 4 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
[['a', 'b', 'c', 'd'], ['e', 'f', 'g','h'], [], []] 
+1

Immagino che dovrebbe essere la risposta accettata in quanto la domanda stava chiedendo un elenco di liste e non un elenco di tuple. O la risposta di Robert nel commento sopra. –

Problemi correlati