Einige sind integriert, um eine Liste in Python aufzufüllen

110

Ich habe eine Liste mit der Größe < N und möchte sie mit einem Wert auf die Größe N auffüllen.

Natürlich kann ich so etwas wie das Folgende verwenden, aber ich bin der Meinung, dass es etwas geben sollte, das ich verpasst habe:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']
Newtover
quelle
Warum willst du das tun? Es gibt wahrscheinlich einen besseren Weg.
Katriel
Ich serialisiere die Liste in eine durch Tabulatoren getrennte Zeichenfolge mit der festen Anzahl von Spalten.
Newtover
Meinst du, du machst so etwas wie '\ t'.join ([1,' ',' ',' ',' '])? Vielleicht können Sie uns mehr darüber erzählen, was Sie implementieren möchten, und dann können wir versuchen, eine Idee zu entwickeln.
Satoru
@ Satoru.Logic: Ja, print >> a_stream, '\ t'.join (the_list) ist alles, was ich implementieren möchte
newtover

Antworten:

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

oder wenn Sie nicht an aOrt und Stelle ändern möchten

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

Sie können jederzeit eine Unterklasse von Listen erstellen und die Methode nach Belieben aufrufen

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

a = MyList(['1'])
b = a.ljust(5, '')
John La Rooy
quelle
3
Das sieht viel besser aus, aber ich erwarte immer noch so etwas wie eine Füll- oder Pad- Methode oder -Funktion =)
Newtover
30

Ich denke, dieser Ansatz ist visueller und pythonischer.

a = (a + N * [''])[:N]
Nuno André
quelle
Ich brauche eine halbe Minute, um zu verstehen. Die akzeptierte Antwort ist viel einfacher.
Richard Möhn
3
@ RichardMöhn "pythonic" bedeutet "idiomatisch". Je länger Sie Python verwenden, desto natürlicher wird diese Syntax.
Nuno André
4
Ich weiß, was "pythonisch" bedeutet. Und ich benutze Python seit 2014 ununterbrochen. Ich finde Ihre Antwort immer noch nicht natürlich.
Richard Möhn
Was macht es pythonisch, eine Zwischenliste zu erstellen?
DylanYoung
1
@ DylanYoung Dies ist nicht der Fall für den ersten Zeitpunkt N < len(a). Dies ist der Fall für die zweite Antwort, die Sie gegeben haben.
kon psych
25

Hierfür gibt es keine eingebaute Funktion. Sie können jedoch die integrierten Funktionen für Ihre Aufgabe erstellen (oder alles: p).

(Geändert von itertools padnoneund takeRezepten)

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)

Verwendung:

>>> list(pad([1,2,3], 7, ''))
[1, 2, 3, '', '', '', '']
kennytm
quelle
6

Die Antwort von gnibbler ist besser, aber wenn Sie ein eingebautes benötigen, können Sie Folgendes verwenden itertools.izip_longest( zip_longestin Py3k):

itertools.izip_longest( xrange( N ), list )

Dadurch wird eine Liste der ( i, list[ i ] )ausgefüllten Tupel an None zurückgegeben. Wenn Sie die Theke loswerden müssen, gehen Sie wie folgt vor:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )
Katriel
quelle
1
Ich wusste über izip_longest Bescheid, aber der resultierende Code sieht nicht gut aus =)
newtover
2
Ich glaube du meinst operator.itemgetter(). Auch die NoneWerte mussten durch ersetzt werden "".
Pylang
5

Sie können auch einen einfachen Generator ohne Einbauten verwenden. Aber ich würde die Liste nicht auffüllen, sondern die Anwendungslogik mit einer leeren Liste umgehen lassen.

Jedenfalls Iterator ohne 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
quelle
4

Wenn Sie mit None anstelle von '' auffüllen möchten, erledigt map () die Aufgabe:

>>> 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
quelle
2
Um ehrlich zu sein, ein + [''] * (N-len (a)) sieht viel klarer aus. Außerdem fehlt es an Casting zur Liste. Aber danke trotzdem.
Newtover
4

more-itertoolsist eine Bibliothek, die ein spezielles paddedTool für diese Art von Problem enthält:

import more_itertools as mit

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

Alternativ können more_itertoolsauch Python- itertools-Rezepte implementiert werden, einschließlich padnoneund takewie von @kennytm erwähnt, sodass sie nicht erneut implementiert werden müssen:

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

Wenn Sie die Standardauffüllung ersetzen möchten None, verwenden Sie ein Listenverständnis:

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

Kennytm verlassen:

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
quelle
1
extra_length = desired_length - len(l)
l.extend(value for _ in range(extra_length))

Dies vermeidet jede zusätzliche Zuordnung, im Gegensatz zu jeder Lösung, die vom Erstellen und Anhängen der Liste abhängt [value] * extra_length. Die "verlängern" -Methode ruft zuerst __length_hint__den Iterator auf und erweitert die Zuordnung um ldiesen Betrag, bevor sie vom Iterator ausgefüllt wird.

Paul Crowley
quelle