166

I have a list of size < N and I want to pad it up to the size N with a value.

Certainly, I can use something like the following, but I feel that there should be something I missed:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']
Ian Mackinnon
  • 13,381
  • 13
  • 51
  • 67
newtover
  • 31,286
  • 11
  • 84
  • 89
  • Why do you want to do this? There is probably a better way. – Katriel Aug 09 '10 at 09:34
  • I serialize the list into a tab-separated string with the fixed number of columns. – newtover Aug 09 '10 at 09:44
  • Do you mean you are doing something like '\t'.join([1,'','','',''])? Maybe you can tell us more about what you intend to implement, then we can try to come up with a idea. – satoru Aug 09 '10 at 10:07
  • @Satoru.Logic: yes, _print >> a_stream, '\t'.join(the_list)_ is all I want to implement – newtover Aug 09 '10 at 12:47

14 Answers14

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

or if you don't want to change a in place

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

you can always create a subclass of list and call the method whatever you please

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

a = MyList(['1'])
b = a.ljust(5, '')
oyvind
  • 1,429
  • 3
  • 14
  • 24
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
47

I think this approach is more visual and pythonic.

a = (a + N * [''])[:N]
Nuno André
  • 4,739
  • 1
  • 33
  • 46
  • 6
    This takes me half a minute to understand. The accepted answer is much more straightforward. – Richard Möhn Dec 11 '19 at 02:43
  • 7
    @RichardMöhn "pythonic" means "idiomatic". The longer you use Python, the more natural you will find this syntax. – Nuno André Dec 20 '19 at 03:37
  • 17
    I know what ‘pythonic’ means. And I've been using Python continuously since 2014. I still don't find your answer natural. – Richard Möhn Dec 21 '19 at 08:33
  • 4
    What makes it pythonic to construct an intermediate throw-away list? – DylanYoung Feb 24 '20 at 17:40
  • @DylanYoung The _two_ intermediate lists don't make it pythonic nor unpythonic, neither makes it the `a` identifier nor the `=` sign. Whether mutating an object or not should depend on the concrete case, but as a general rule I tend to treat any object as immutable unless there is good reason why it should not be. If you think mutating lists is an inherently better practice or more "pythonic", it's up to you. – Nuno André Feb 24 '20 at 18:54
  • @NunoAndré Nothing to do with mutating anything. You create an intermediate copy here: `a + N * ['']`. You then throw that intermediate list out by slicing it. You already know the length you want. There is literally nothing more pythonic about your answer than any others. It's just poor programming practice (in any language unless you're positive that your interpreter/compiler can optimize out the duplicate list). – DylanYoung Feb 25 '20 at 20:28
  • 2
    This answer unlike the accepted one enforces a length of `N` which may be desirable. Depends on application and that is what makes this answer useful. – kon psych Mar 18 '20 at 17:17
  • @konpsych So does this one: `new_a = a + [''] * (N - len(a))` – DylanYoung Apr 03 '20 at 17:55
  • 1
    @DylanYoung this is not the case for first when `N < len(a)`. It is the case for the second answer you provided. – kon psych Apr 06 '20 at 15:24
  • True. I don't really like that answer either. – DylanYoung Apr 07 '20 at 04:48
  • @konpsych Sorry, you are making assumption that OP _explicitly_ says otherwise: "I have a list of size < N and I want to pad it up to the size N with a value" – Abel Cheung Nov 25 '20 at 00:22
33

There is no built-in function for this. But you could compose the built-ins for your task (or anything :p).

(Modified from itertool's padnone and take recipes)

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, '', '', '', '']
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
14

more-itertools is a library that includes a special padded tool for this kind of problem:

import more_itertools as mit

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

Alternatively, more_itertools also implements Python itertools recipes including padnone and take as mentioned by @kennytm, so they don't have to be reimplemented:

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

If you wish to replace the default None padding, use a list comprehension:

["" if i is None else i for i in mit.take(N, mit.padnone(a))]
# [1, '', '', '', '']
pylang
  • 40,867
  • 14
  • 129
  • 121
8

gnibbler's answer is nicer, but if you need a builtin, you could use itertools.izip_longest (zip_longest in Py3k):

itertools.izip_longest( xrange( N ), list )

which will return a list of tuples ( i, list[ i ] ) filled-in to None. If you need to get rid of the counter, do something like:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )
Katriel
  • 120,462
  • 19
  • 136
  • 170
5

You could also use a simple generator without any build ins. But I would not pad the list, but let the application logic deal with an empty list.

Anyhow, iterator without 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
  • 3,225
  • 1
  • 26
  • 26
5

If you want to pad with None instead of '', map() does the job:

>>> 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
  • 722
  • 12
  • 12
  • 2
    To say frankly, _a+['']*(N-len(a))_ looks much clearer. Besides, it lacks casting to list. But thank you anyway. – newtover Jan 06 '11 at 20:53
5

Using iterators and taking advantage of the default argument for next:

i = iter(a)
a = [next(i, '') for _ in range(N)]

Short explanation:

Either way we want to produce N items. Hence the for _ in range(N). Then the elements should be as much as we can from a and the rest ''. Using an iterator over a we grab all possible elements, and when we get StopIteration, the default will be returned which is ''.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
4
extra_length = desired_length - len(l)
l.extend(value for _ in range(extra_length))

This avoids any extra allocation, unlike any solution that depends on creating and appending the list [value] * extra_length. The "extend" method first calls __length_hint__ on the iterator, and extends the allocation for l by that much before filling it in from the iterator.

Paul Crowley
  • 1,656
  • 1
  • 14
  • 26
  • More concisely, `a.extend((N-len(a))*[padding_value])` (I'm using OP notation). – mmj Jan 28 '21 at 11:06
  • Your proposal involves allocating a list, then using "extend" to append it. Mine avoids the extra allocation; no new list is created, only a generator object. – Paul Crowley Jan 29 '21 at 14:02
4

you can use * iterable unpacking operator:

N = 5
a = [1]

pad_value = ''
pad_size = N - len(a)

final_list = [*a, *[pad_value] * pad_size]
print(final_list)

output:

[1, '', '', '', '']
kederrac
  • 16,819
  • 6
  • 32
  • 55
3

To go off of 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]
Markus Amalthea Magnuson
  • 8,415
  • 4
  • 41
  • 49
aberger
  • 2,299
  • 4
  • 17
  • 29
2

Adding the padding before the list of elements

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

Adding the padding after the list of elements

a += [''] * (N - len(a))
code_conundrum
  • 529
  • 6
  • 12
1

Adding to the existing list with np.repeat:

import numpy as np
a + list(np.repeat([''], (N - len(a))))
bshelt141
  • 1,183
  • 15
  • 31
-2

A pythonic way to pad your list with empty elements is using list comprehension.

        my_list = [1,2]
        desired_len = 3
        # Ensure that the length of my list is 3 elements
        [my_list.extend(['']) for _ in range(desired_len - len(my_list))]
        [my_list.pop() for _ in range(len(my_list)-desired_len )]
Drew M.
  • 49
  • 6