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

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

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]

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

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

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

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)

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

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]


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.