Algunos incorporados para rellenar una lista en Python

110

Tengo una lista de tamaño < N y quiero rellenarla hasta el tamaño N con un valor.

Ciertamente, puedo usar algo como lo siguiente, pero creo que debería haber algo que me perdí:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']
newtover
fuente
¿Por qué quieres hacer esto? Probablemente haya una forma mejor.
Katriel
Serializo la lista en una cadena separada por tabulaciones con el número fijo de columnas.
newtover
¿Quiere decir que está haciendo algo como '\ t'.join ([1,' ',' ',' ',' '])? Tal vez pueda contarnos más sobre lo que pretende implementar, luego podemos intentar tener una idea.
Satoru
@ Satoru.Logic: sí, imprimir >> a_stream, '\ t'.join (the_list) es todo lo que quiero implementar
newtover

Respuestas:

165
a += [''] * (N - len(a))

o si no quieres cambiarte ade lugar

new_a = a + [''] * (N - len(a))

siempre puedes crear una subclase de lista y llamar al método como quieras

class MyList(list):
    def ljust(self, n, fillvalue=''):
        return self + [fillvalue] * (n - len(self))

a = MyList(['1'])
b = a.ljust(5, '')
John La Rooy
fuente
3
Esto se ve mucho mejor, pero todavía espero algo como un método o función de relleno o relleno =)
newtover
30

Creo que este enfoque es más visual y pitónico.

a = (a + N * [''])[:N]
Nuno André
fuente
Esto me lleva medio minuto entenderlo. La respuesta aceptada es mucho más sencilla.
Richard Möhn
3
@ RichardMöhn "pitónico" significa "idiomático". Cuanto más tiempo use Python, más natural encontrará esta sintaxis.
Nuno André
4
Sé lo que significa "pitónico". Y he estado usando Python continuamente desde 2014. Todavía no encuentro su respuesta natural.
Richard Möhn
¿Qué hace que sea pitónico construir una lista desechable intermedia?
DylanYoung
1
@DylanYoung este no es el caso para el primero cuando N < len(a). Es el caso de la segunda respuesta que proporcionó.
kon psych
25

No hay una función incorporada para esto. Pero podría componer los elementos integrados para su tarea (o cualquier cosa: p).

(Modificado de itertool's padnoney takerecetas)

from itertools import chain, repeat, islice

def pad_infinite(iterable, padding=None):
   return chain(iterable, repeat(padding))

def pad(iterable, size, padding=None):
   return islice(pad_infinite(iterable, padding), size)

Uso:

>>> list(pad([1,2,3], 7, ''))
[1, 2, 3, '', '', '', '']
Kennytm
fuente
6

La respuesta de gnibbler es mejor, pero si necesita un incorporado, podría usar itertools.izip_longest( zip_longesten Py3k):

itertools.izip_longest( xrange( N ), list )

que devolverá una lista de tuplas ( i, list[ i ] )completadas en Ninguno. Si necesita deshacerse del mostrador, haga algo como:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )
Katriel
fuente
1
Que sabía de izip_longest pero que resulta el código no se ve agradable =)
newtover
2
Creo que te refieres operator.itemgetter(). También los Nonevalores debían ser reemplazados por "".
pylang
5

También puede usar un generador simple sin ningún tipo de construcción. Pero no rellenaría la lista, sino que dejaría que la lógica de la aplicación se ocupara de una lista vacía.

De todos modos, iterador sin buildins

def pad(iterable, padding='.', length=7):
    '''
    >>> iterable = [1,2,3]
    >>> list(pad(iterable))
    [1, 2, 3, '.', '.', '.', '.']
    '''
    for count, i in enumerate(iterable):
        yield i
    while count < length - 1:
        count += 1
        yield padding

if __name__ == '__main__':
    import doctest
    doctest.testmod()
Thierry
fuente
4

Si desea rellenar con None en lugar de '', map () hace el trabajo:

>>> map(None,[1,2,3],xrange(7))

[(1, 0), (2, 1), (3, 2), (None, 3), (None, 4), (None, 5), (None, 6)]

>>> zip(*map(None,[1,2,3],xrange(7)))[0]

(1, 2, 3, None, None, None, None)
Federico
fuente
2
Para decirlo francamente, a + [''] * (N-len (a)) parece mucho más claro. Además, carece de casting para listar. Pero gracias de todas maneras.
newtover
4

more-itertoolses una biblioteca que incluye una paddedherramienta especial para este tipo de problemas:

import more_itertools as mit

list(mit.padded(a, "", N))
# [1, '', '', '', '']

Alternativamente, more_itertoolstambién implementa recetas de herramientas de iteración de Python que incluyen padnoney takecomo lo menciona @kennytm, para que no tengan que volver a implementarse:

list(mit.take(N, mit.padnone(a)))
# [1, None, None, None, None]

Si desea reemplazar el Nonerelleno predeterminado , use una lista de comprensión:

["" if i is None else i for i in mit.take(N, mit.padnone(a))]
# [1, '', '', '', '']
pylang
fuente
2

Para salir de kennytm:

def pad(l, size, padding):
    return l + [padding] * abs((len(l)-size))

>>> l = [1,2,3]
>>> pad(l, 7, 0)
[1, 2, 3, 0, 0, 0, 0]
aberger
fuente
2

puede usar un * operador de desempaquetado iterable :

N = 5
a = [1]

pad_value = ''
pad_size = N - len(a)

final_list = [*a, *[pad_value] * pad_size]
print(final_list)

salida:

[1, '', '', '', '']
kederrac
fuente
1
extra_length = desired_length - len(l)
l.extend(value for _ in range(extra_length))

Esto evita cualquier asignación adicional, a diferencia de cualquier solución que dependa de crear y agregar la lista [value] * extra_length. El método "extender" primero llama __length_hint__al iterador y extiende la asignación en lesa cantidad antes de completarlo desde el iterador.

Paul Crowley
fuente