Certains intégrés pour remplir une liste en python

110

J'ai une liste de taille < N et je veux la compléter à la taille N avec une valeur.

Certes, je peux utiliser quelque chose comme ce qui suit, mais je pense qu'il devrait y avoir quelque chose que j'ai manqué:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']
Newtover
la source
Pourquoi veux-tu faire cela? Il existe probablement un meilleur moyen.
Katriel
Je sérialise la liste dans une chaîne séparée par des tabulations avec le nombre fixe de colonnes.
newtover
Voulez-vous dire que vous faites quelque chose comme '\ t'.join ([1,' ',' ',' ',' '])? Peut-être pourriez-vous nous en dire plus sur ce que vous comptez mettre en œuvre, puis nous pourrons essayer de trouver une idée.
satoru
@ Satoru.Logic: oui, imprimez >> a_stream, '\ t'.join (the_list) est tout ce que je veux implémenter
newtover

Réponses:

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

ou si vous ne voulez pas changer ade place

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

vous pouvez toujours créer une sous-classe de liste et appeler la méthode comme bon vous semble

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

a = MyList(['1'])
b = a.ljust(5, '')
John La Rooy
la source
3
Cela ressemble beaucoup mieux, mais je me attends encore quelque chose comme un remplissage ou pad méthode ou fonction =)
newtover
30

Je pense que cette approche est plus visuelle et pythonique.

a = (a + N * [''])[:N]
Nuno André
la source
Cela me prend une demi-minute pour comprendre. La réponse acceptée est beaucoup plus simple.
Richard Möhn
3
@ RichardMöhn "pythonique" signifie "idiomatique". Plus vous utilisez Python longtemps, plus vous trouverez cette syntaxe naturelle.
Nuno André
4
Je sais ce que signifie «pythonique». Et j'utilise Python en continu depuis 2014. Je ne trouve toujours pas votre réponse naturelle.
Richard Möhn
Qu'est-ce qui rend pythonique la construction d'une liste intermédiaire à jeter?
DylanYoung le
1
@DylanYoung ce n'est pas le cas pour le premier quand N < len(a). C'est le cas de la deuxième réponse que vous avez fournie.
kon psych le
25

Il n'y a pas de fonction intégrée pour cela. Mais vous pouvez composer les éléments intégrés pour votre tâche (ou quoi que ce soit: p).

(Modifié à partir d'itertool padnoneet de takerecettes)

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)

Usage:

>>> list(pad([1,2,3], 7, ''))
[1, 2, 3, '', '', '', '']
KennyTM
la source
6

La réponse de gnibbler est plus agréable, mais si vous avez besoin d'un intégré, vous pouvez utiliser itertools.izip_longest( zip_longestdans Py3k):

itertools.izip_longest( xrange( N ), list )

qui renverra une liste de tuples ( i, list[ i ] )remplis à Aucun. Si vous devez vous débarrasser du compteur, faites quelque chose comme:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )
Katriel
la source
1
Je connaissais izip_longest mais le code résultant n'a pas l'air sympa =)
newtover
2
Je crois que tu veux dire operator.itemgetter(). Les Nonevaleurs devaient également être remplacées par "".
pylang
5

Vous pouvez également utiliser un générateur simple sans build ins. Mais je ne remplirais pas la liste, mais laisserais la logique de l'application traiter une liste vide.

Quoi qu'il en soit, itérateur sans 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
la source
4

Si vous voulez remplir avec None au lieu de '', map () fait le travail:

>>> 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
la source
2
Pour dire franchement, a + [''] * (N-len (a)) semble beaucoup plus clair. De plus, il manque un casting à la liste. Mais merci quand même.
newtover
4

more-itertoolsest une bibliothèque qui inclut un paddedoutil spécial pour ce genre de problème:

import more_itertools as mit

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

Sinon, more_itertoolsimplémente également les recettes Python itertools, y compris padnoneet takecomme mentionné par @kennytm, afin qu'elles n'aient pas à être réimplémentées:

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

Si vous souhaitez remplacer le Noneremplissage par défaut , utilisez une compréhension de liste:

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

Pour sortir du 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
la source
2

vous pouvez utiliser l' * opérateur de déballage itérable :

N = 5
a = [1]

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

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

production:

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

Cela évite toute allocation supplémentaire, contrairement à toute solution qui dépend de la création et de l'ajout de la liste [value] * extra_length. La méthode "extend" appelle d'abord __length_hint__l'itérateur, et étend l'allocation pour lautant avant de la remplir à partir de l'itérateur.

Paul Crowley
la source