J'ai une liste de taille < N et je veux la remplir jusqu'à 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, '', '', '', '']
a += [''] * (N - len(a))
ou si vous ne voulez pas changer a
en 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, '')
Je pense que cette approche est plus visuelle et Pythonique.
a = (a + N * [''])[:N]
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 n'importe quoi: p).
(Modifié à partir des recettes padnone
et take
d'itertool)
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, '', '', '', '']
la réponse de gnibbler est plus agréable, mais si vous avez besoin d'une fonction intégrée, vous pouvez utiliser itertools.izip_longest
(Zip_longest
en Py3k):
itertools.izip_longest( xrange( N ), list )
qui renverra une liste de tuples ( i, list[ i ] )
rempli à Aucun. Si vous devez vous débarrasser du comptoir, faites quelque chose comme:
map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )
Si vous souhaitez 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)
Vous pouvez également utiliser un générateur simple sans aucune compilation. Mais je ne remplirais pas la liste, mais laisserais la logique d'application gérer 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 __== '__main__':
import doctest
doctest.testmod()
more-itertools
est une bibliothèque qui inclut un outil spécial padded
pour ce type de problème:
import more_itertools as mit
list(mit.padded(a, "", N))
# [1, '', '', '', '']
Alternativement, more_itertools
implémente également Python recettes itertools y compris padnone
et take
= comme mentionné par @kennytm, ils n'ont donc pas besoin d'être réimplémentés:
list(mit.take(N, mit.padnone(a)))
# [1, None, None, None, None]
Si vous souhaitez remplacer le remplissage par défaut None
, utilisez une compréhension de liste:
["" if i is None else i for i in mit.take(N, mit.padnone(a))]
# [1, '', '', '', '']
Pour quitter 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]
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__
sur l'itérateur, et étend d'autant l'allocation pour l
avant de le remplir depuis l'itérateur.