2010-03-15 14 views
19

Voglio scrivere una funzione che ripristina una lista [1,5,3,6,...] e dà [1,1,5,5,3,3,6,6,...] qualche idea su come farlo? grazieduplica ogni membro in una lista - python

+2

Suoni di lavoro domestico. Esistono modi migliori per lavorare con un elenco rispetto alla duplicazione degli elementi. –

risposta

12
>>> a = [1, 2, 3] 
>>> b = [] 
>>> for i in a: 
    b.extend([i, i]) 


>>> b 
[1, 1, 2, 2, 3, 3] 

o

>>> [a[i//2] for i in range(len(a)*2)] 
[1, 1, 2, 2, 3, 3] 
+0

Dovresti usare '//' anche per la divisione floor in Python 2. –

+0

@Mike: sicuro che hai ragione, tranne ovviamente nella divisione '/' assicura che 'int' viene restituito. – SilentGhost

38
>>> a = range(10) 
>>> [val for val in a for _ in (0, 1)] 
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9] 

N.B. _ viene tradizionalmente utilizzato come nome variabile segnaposto in cui non si desidera fare nulla con il contenuto della variabile. In questo caso è solo usato per generare due valori per ogni volta intorno al ciclo esterno.

Per trasformare questo da un elenco in un generatore, sostituire le parentesi quadre con le parentesi tonde.

+1

'_' è, in questi giorni, utilizzato per i18n/l10n (google). Tendo ancora ad usarlo * se * so che non ci sarà un i18n in questo modulo. Altrimenti I (vorrebbe) usare '__' (due underscore). –

1

vorrei utilizzare

import itertools 
foo = [1, 5, 3, 6] 
new = itertools.chain.from_iterable([item, item] for item in foo) 

new sarà un iteratore che pigramente itera oltre gli elementi duplicati. Se è necessario calcolare l'elenco effettivo, è possibile eseguire list(new) o utilizzare una delle altre soluzioni.

+1

o più breve: 'itertools.chain.from_iterable (itertools.izip (foo, foo))' –

+0

Ho considerato quel codice che è più breve ma non mi sembra più chiaro. –

6

Se hai già il roundrobin ricetta descritto nella documentazione per itertools -e è abbastanza a portata di mano, allora si può semplicemente utilizzare

roundrobin(my_list, my_list) 
+0

+1, questo è un buon modo per realizzare questo. –

1

Per quanto Guido non piace agli operatori funzionali, possono essere abbastanza dannatamente a portata di mano:

>>> from operator import add 
>>> a = range(10) 
>>> b = reduce(add, [(x,x) for x in a]) 
+0

Nel caso di ridurre, maneggevole spesso significa incredibilmente lento. È importante misurare cosa sta facendo 'reduce'. Spesso, è scioccante quanto il calcolo riduca le forze. –

+0

Ho creato uno script di test con tutti i metodi su questa pagina con baselist = range (10) e 1,000,000 iterations. Il più lento ha preso 5.094 secondi e il più veloce ha preso 3.622 secondi. Il mio esempio di riduzione ha richiesto 3.906 secondi. –

+1

'range (10)' è piccolo, quindi la complessità paga un piccolo ruolo. Questa soluzione è quadratica; tutti gli altri che vedo qui sono lineari. Inoltre, alcuni degli altri mi sembrano più leggibili. –

8

userei zip e itertools.chain.

>>> import itertools 
>>> l = [1,5,3,6,16] 
>>> list(itertools.chain(*zip(l,l))) 
[1, 1, 5, 5, 3, 3, 6, 6, 16, 16] 

Nota: ho usato solo list di consumare il generatore per renderla adatta per la stampa. Probabilmente non hai bisogno della chiamata list nel tuo codice ...

1

È possibile utilizzare la moltiplicazione della lista. Caso hai bisogno di ogni membro della lista insieme basta usare il metodo ordinato.

>>> lst = [1,2,3,4] 
>>> sorted(lst*2) 
[1,1,2,2,3,3,4,4] 
+0

E se si desidera mantenere l'ordine della lista originale? Che dire se gli articoli nell'elenco sono non ordinabili? – Moberg

Problemi correlati