Niektóre wbudowane elementy uzupełniające listę w Pythonie


110

Mam listę o rozmiarze < N i chcę dopełnić ją do rozmiaru N wartością.

Oczywiście mogę użyć czegoś podobnego do następującego, ale czuję, że powinno być coś, co przegapiłem:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']

Dlaczego chcesz to zrobić? Prawdopodobnie jest lepszy sposób.
Katriel

Serializuję listę w postaci ciągu rozdzielanego tabulatorami ze stałą liczbą kolumn.
newtover

Czy to znaczy, że robisz coś takiego jak '\ t'.join ([1,' ',' ',' ',' '])? Może możesz nam powiedzieć więcej o tym, co zamierzasz wdrożyć, wtedy możemy spróbować wpaść na pomysł.
satoru

@ Satoru.Logic: yes, print >> a_stream, '\ t'.join (the_list) to wszystko, co chcę zaimplementować
newtover

Odpowiedzi:


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

lub jeśli nie chcesz zmieniać amiejsca

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

zawsze możesz utworzyć podklasę listy i wywołać metodę, jak chcesz

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

a = MyList(['1'])
b = a.ljust(5, '')

3
To wygląda o wiele lepiej, ale wciąż coś jak oczekiwać wypełnienia lub pad metody lub funkcji =)
newtover

30

Myślę, że to podejście jest bardziej wizualne i pytoniczne.

a = (a + N * [''])[:N]

Zrozumienie tego zajmuje mi pół minuty. Przyjęta odpowiedź jest znacznie prostsza.
Richard Möhn,

3
@ RichardMöhn „pythonic” oznacza „idiomatyczny”. Im dłużej używasz Pythona, tym bardziej naturalna będzie ta składnia.
Nuno André

4
Wiem, co oznacza „pytoniczny”. Używam Pythona nieprzerwanie od 2014 roku. Twoja odpowiedź nadal nie wydaje mi się naturalna.
Richard Möhn

Co sprawia, że ​​tworzenie pośredniej listy rzeczy do wyrzucenia jest pythonowe?
DylanYoung

1
@DylanYoung tak nie jest w przypadku pierwszego kiedy N < len(a). Tak jest w przypadku drugiej podanej przez Ciebie odpowiedzi.
kon psych

25

Nie ma do tego wbudowanej funkcji. Ale możesz skomponować wbudowane funkcje do swojego zadania (lub cokolwiek: p).

(Zmodyfikowane na podstawie itertool's padnonei takeprzepisów)

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)

Stosowanie:

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

6

Odpowiedź gnibblera jest ładniejsza, ale jeśli potrzebujesz wbudowanego, możesz użyć itertools.izip_longest( zip_longestw Py3k):

itertools.izip_longest( xrange( N ), list )

co zwróci listę ( i, list[ i ] )wypełnionych krotek na Brak. Jeśli chcesz pozbyć się licznika, zrób coś takiego:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )

1
Wiedziałem o izip_longest, ale wynikowy kod nie wygląda ładnie =)
newtover

2
Myślę, że masz na myśli operator.itemgetter(). Również Nonewartości, które należało zastąpić "".
pylang

5

Możesz także użyć prostego generatora bez żadnych wbudowanych programów. Ale nie wypełniłbym listy, ale pozwoliłbym logice aplikacji zająć się pustą listą.

W każdym razie iterator bez 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

Jeśli chcesz uzupełnić brakiem zamiast „”, map () wykona zadanie:

>>> 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
Szczerze mówiąc, a + [''] * (N-len (a)) wygląda znacznie jaśniej. Poza tym brakuje mu castingu do listy. Ale mimo wszystko dziękuję.
newtover

4

more-itertoolsto biblioteka, która zawiera specjalne paddednarzędzie do tego rodzaju problemów:

import more_itertools as mit

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

Alternatywnie more_itertoolsimplementuje również receptury Python itertools, w tym padnonei takejak wspomniał @kennytm, więc nie trzeba ich ponownie wdrażać:

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

Jeśli chcesz zamienić domyślne Nonewypełnienie, użyj wyrażenia listowego:

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

2

Aby wyjść z 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))

Pozwala to uniknąć dodatkowej alokacji, w przeciwieństwie do jakiegokolwiek rozwiązania, które polega na tworzeniu i dołączaniu listy [value] * extra_length. Metoda „rozszerz” najpierw wywołuje __length_hint__iterator i rozszerza alokację o ltyle przed wypełnieniem jej z iteratora.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.