sacar - llenar una lista en python
Creación de una lista de elementos de listas individuales multiplicada n veces (5)
@kirelagin sugirió una versión sin bucles for
, aquí hay uno que tampoco tiene lambda
(tenga en cuenta que la solución de @AshwiniChaudhary es más legible)
>>> from itertools import repeat
>>> a = [''x'',''y'',''z'']
>>> b = [1,2,3]
>>> map(list, map(repeat, a, b))
[[''x''], [''y'', ''y''], [''z'', ''z'', ''z'']]
>>> map(repeat, a, b)
[repeat(''x'', 1), repeat(''y'', 2), repeat(''z'', 3)]
crea una lista de objetos repeat
(use imap
en Python 2.x si desea un iterador perezoso en lugar de una lista) que no ocupen espacio adicional en la memoria, estos son geniales si solo desea iterar sobre los elementos en su lugar de almacenarlos)
Soy bastante nuevo en Python, y creo que este debería ser un problema bastante común, pero no puedo encontrar una solución. Ya he consultado esta página y he encontrado que es útil para un elemento, pero me cuesta ampliar el ejemplo a varios elementos sin utilizar un ciclo ''for''. Estoy ejecutando este código para 250 caminantes a través de Emcee, así que estoy buscando la forma más rápida posible.
Tengo una lista de números, a = [x,y,z]
que quiero repetir b = [1,2,3]
veces (por ejemplo), así que termino con una lista de listas:
[
[x],
[y,y],
[z,z,z]
]
El ciclo ''for'' que tengo es:
c = [ ]
for i in range (0,len(a)):
c.append([a[i]]*b[i])
Lo cual hace exactamente lo que quiero, pero significa que mi código es insoportablemente lento. También intenté ingenuamente convertir ayb en matrices y hacer [a]*b
con la esperanza de que se multiplicara elemento por elemento, pero no alegría.
Aquí hay una versión sin bucles si no te gustan por alguna razón:
map(lambda v: [v[0]]*v[1], zip(a,b))
También debería advertirte que esta versión es un poco más lenta que una lista de comprensión:
$ a = [''hi'']*100
$ b = [20]*100
$ %timeit map(lambda v: [v[0]]*v[1], zip(a,b))
10000 loops, best of 3: 101 us per loop
%timeit [[x]*y for x,y in zip(a,b)]
10000 loops, best of 3: 74.1 us per loop
También te recomiendo usar itertools.izip
lugar de zip
si estás en Python 2.
La forma más rápida de hacerlo es con map () y operator.mul () :
>>> from operator import mul
>>> map(mul, [[''x''], [''y''], [''z'']], [1, 2, 3])
[[''x''], [''y'', ''y''], [''z'', ''z'', ''z'']]
Puede usar zip
y una lista de comprensión aquí:
>>> a = [''x'',''y'',''z'']
>>> b = [1,2,3]
>>> [[x]*y for x,y in zip(a,b)]
[[''x''], [''y'', ''y''], [''z'', ''z'', ''z'']]
o:
>>> [[x for _ in xrange(y)] for x,y in zip(a,b)]
[[''x''], [''y'', ''y''], [''z'', ''z'', ''z'']]
zip
creará primero toda la lista en memoria, para obtener un iterador use itertools.izip
En caso de que a
contenga objetos mutables como listas o listas de listas, entonces puede que tenga que usar copy.deepcopy
aquí porque la modificación de una copia también cambiará otras copias .:
>>> from copy import deepcopy as dc
>>> a = [[1 ,4],[2, 5],[3, 6, 9]]
>>> f = [[dc(x) for _ in xrange(y)] for x,y in zip(a,b)]
#now all objects are unique
>>> [[id(z) for z in x] for x in f]
[[172880236], [172880268, 172880364], [172880332, 172880492, 172880428]]
comparaciones de tiempo (ignorando las importaciones):
>>> a = [''x'',''y'',''z'']*10**4
>>> b = [100,200,300]*10**4
>>> %timeit [[x]*y for x,y in zip(a,b)]
1 loops, best of 3: 104 ms per loop
>>> %timeit [[x]*y for x,y in izip(a,b)]
1 loops, best of 3: 98.8 ms per loop
>>> %timeit map(lambda v: [v[0]]*v[1], zip(a,b))
1 loops, best of 3: 114 ms per loop
>>> %timeit map(list, map(repeat, a, b))
1 loops, best of 3: 192 ms per loop
>>> %timeit map(list, imap(repeat, a, b))
1 loops, best of 3: 211 ms per loop
>>> %timeit map(mul, [[x] for x in a], b)
1 loops, best of 3: 107 ms per loop
>>> %timeit [[x for _ in xrange(y)] for x,y in zip(a,b)]
1 loops, best of 3: 645 ms per loop
>>> %timeit [[x for _ in xrange(y)] for x,y in izip(a,b)]
1 loops, best of 3: 680 ms per loop
>>> from itertools import repeat
>>> from itertools import starmap
>>> a = [''x'',''y'',''z'']
>>> b = [1,2,3]
>>> starmap(repeat,zip(a,b))
starmap
devuelve un iterable que contiene valores iguales al resultado de llamar a repeat
con argumentos iguales a los valores contenidos en una tupla, en este caso por ejemplo (''x'',1)
.
>>> for p in starmap(repeat,zip(a,b)):
print(list(p))
[''x'']
[''y'', ''y'']
[''z'', ''z'', ''z'']