Деякі вбудовані для вкладки списку в python


110

У мене є список розміру < N, і я хочу змінити його до розміру N зі значенням.

Звичайно, я можу використовувати щось на кшталт наступного, але я відчуваю, що має бути щось, що я пропустив:

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

Чому ти хочеш це робити? Мабуть, кращий спосіб.
Катріель

Я серіалізую список у рядок, розділений на вкладки, із фіксованою кількістю стовпців.
newtover

Ви маєте на увазі, що ви робите щось на кшталт '\ t'.join ([1,' ',' ',' ',' '])? Можливо, ви можете розповісти нам більше про те, що ви маєте намір здійснити, тоді ми можемо спробувати придумати ідею.
satoru

@ Satoru.Logic: так, надрукувати >> a_stream, '\ t'.join (the_list) - все, що я хочу реалізувати
newtover

Відповіді:


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

або якщо ви не хочете змінюватися aна місці

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

Ви завжди можете створити підклас списку і викликати метод, що завгодно

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

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

3
Це виглядає набагато краще, але я все одно очікую щось подібне до методу заповнення або колодки або функції =)
newtover

30

Я думаю, що цей підхід є більш візуальним та пітонічним.

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

На це мені потрібно півхвилини, щоб зрозуміти. Прийнята відповідь набагато простіша.
Річард

3
@ РічардМен "пітонічний" означає "ідіоматичний". Чим довше ви використовуєте Python, тим природніше ви знайдете цей синтаксис.
Нуно Андре

4
Я знаю, що означає «пітонік». І я використовую Python постійно з 2014 року. Я досі не вважаю вашу відповідь природним.
Річард

Що робить пітонічним побудову проміжного списку викидання?
DylanYoung

1
@DylanYoung це не так в першу чергу, коли N < len(a). Це справа другої відповіді, яку ви надали.
kon psych

25

Для цього немає вбудованої функції. Але ви можете скласти додатки для свого завдання (або що-небудь: p).

(Змінено з itertool's padnoneі takeрецептів)

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)

Використання:

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

6

Відповідь gnibbler є приємнішою, але якщо вам потрібен вбудований, ви можете використовувати itertools.izip_longest( zip_longestв Py3k):

itertools.izip_longest( xrange( N ), list )

який поверне список кортежів, ( i, list[ i ] )заповнених None. Якщо вам потрібно позбутися лічильника, зробіть щось на кшталт:

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

1
Я знав про izip_lo Long, але в результаті код виглядає не дуже добре =)
newtover

2
Я вважаю, ти маєш на увазі operator.itemgetter(). Також Noneзначення, які потрібно замінити "".
pylang

5

Ви також можете використовувати простий генератор без будь-яких вбудованих модулів. Але я б не вкладав цей список, а дозволю логіці програми мати справу з порожнім списком.

У всякому разі, ітератор без збірок

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

Якщо ви хочете виконати накладку на "None" замість "", map () виконує завдання:

>>> 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
Відверто кажучи, a + [''] * (N-len (a)) виглядає набагато чіткіше. Крім того, йому не вистачає кастингу для переліку. Але дякую все одно.
newtover

4

more-itertoolsце бібліотека, яка включає спеціальний paddedінструмент для подібного роду проблем:

import more_itertools as mit

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

Крім того, more_itertoolsтакож реалізуються рецепти itertools Python, включаючи padnoneта takeяк зазначено у @kennytm, тому їх не потрібно повторно виконувати:

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

Якщо ви хочете замінити Noneпрокладку за замовчуванням , використовуйте розуміння списку:

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

2

Щоб вийти з 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))

Це дозволяє уникнути зайвого розподілу на відміну від будь-якого рішення, яке залежить від створення та додавання списку [value] * extra_length. Спосіб "розширити" спочатку викликає __length_hint__ітератор і продовжує виділення на lце набагато, перш ніж заповнити його з ітератора.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.