2016-02-05 15 views
10

Sto provando a generare rapidamente un elenco con il contenuto di due diversi array di dimensioni n e n/2. Per fare un esempio:Tentativo di comprensione degli elenchi Python con due variabili di diversi intervalli

A = [70, 60, 50, 40, 30, 20, 10, 0] 
B = [1, 2, 3, 4] 

desidero di generare qualcosa come

[(A[x], B[y]) for x in range(len(A)) for y in range(len(B))] 

Capisco la seconda per affermazione è la nidificato ciclo for dopo la "x" uno. Sto cercando di ottenere il contenuto del nuovo array per essere

A[0], B[0] 
A[1], B[1] 
A[2], B[2] 
A[3], B[3] 
A[4], B[0] 
A[5], B[1] 
A[6], B[2] 
A[7], B[3] 

Qualcuno potrebbe indicarmi la giusta direzione?

risposta

20

Non utilizzare cicli nidificati; stai accoppiando A e B, con B ripetendo se necessario. Quello che vi serve è zip() (per fare il pairing), e itertools.cycle() (a ripetere B):

from itertools import cycle 

zip(A, cycle(B)) 

Se B sta andando sempre essere la metà delle dimensioni di A, si potrebbe anche semplicemente fare doppio B:

zip(A, B + B) 

Demo:

>>> from itertools import cycle 
>>> A = [70, 60, 50, 40, 30, 20, 10, 0] 
>>> B = [1, 2, 3, 4] 
>>> zip(A, cycle(B)) 
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)] 
>>> zip(A, B + B) 
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)] 

Nei casi in cui non si sa quale sia il più lungo lista, è possibile utilizzare min() e max() di scegliere quali uno per ciclo:

zip(max((A, B), key=len), cycle(min((A, B), key=len)) 

o per un numero arbitrario di liste fare coppia, ciclo di loro tutti ma utilizzare itertools.islice() per limitare le cose per la lunghezza massima:

inputs = (A, B) # potentially more 
max_length = max(len(elem) for elem in inputs) 
zip(*(islice(cycle(elem), max_length) for elem in inputs)) 

Demo:

>>> from itertools import islice 
>>> inputs = (A, B) # potentially more 
>>> max_length = max(len(elem) for elem in inputs) 
>>> zip(*(islice(cycle(elem), max_length) for elem in inputs)) 
[(70, 1), (60, 2), (50, 3), (40, 4), (30, 1), (20, 2), (10, 3), (0, 4)] 
+0

Questo è perfetto. Grazie mille. Ho provato a utilizzare la funzione zip() ma ricevevo solo coppie fino a len (B). Non avevo idea di poter fare zip (A, B + B). –

+1

@ A.K .: 'zip()' termina alla lunghezza più breve. Il trucco è quindi quello di rendere 'A' il più breve. –

+0

Un altro modo per il numero arbitrario di casi, usando islice sul ** esterno ** del file zip: 'lista (islice (zip (* mappa (ciclo, input)), max (map (len, input))))' . –

5

Provare a utilizzare un solo ciclo for invece di due e havin g il secondo torna a 0 una volta che supera la sua lunghezza.

[(A[x], B[x%len(B)]) for x in range(len(A))] 

Si noti che questo funzionerà solo se A è la lista più lunga. Se si conosce B sarà sempre la metà delle dimensioni di A è anche possibile utilizzare questo:

list(zip(A, B*2)) 
10

[(A[x % len(A)], B[x % len(B)]) for x in range(max(len(A), len(B)))]

questo funzionerà se A è la lista più grande. :)

+0

Esattamente quello che direi, buona risposta. – AMACB

Problemi correlati