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, '', '', '', '']

¿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, '')

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]

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, '', '', '', '']

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 ) )

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()

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)

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, '', '', '', '']

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]


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.