Some built-in to pad a list in python
Asked Answered
A

14

174

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, '', '', '', '']
Ashburn answered 9/8, 2010 at 9:30 Comment(4)
Why do you want to do this? There is probably a better way.Emmerie
I serialize the list into a tab-separated string with the fixed number of columns.Ashburn
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.Quiberon
@Satoru.Logic: yes, print >> a_stream, '\t'.join(the_list) is all I want to implementAshburn
P
269
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, '')
Patron answered 9/8, 2010 at 9:43 Comment(0)
O
51

I think this approach is more visual and pythonic.

a = (a + N * [''])[:N]
Ostler answered 7/10, 2016 at 18:18 Comment(11)
This takes me half a minute to understand. The accepted answer is much more straightforward.Springer
@RichardMöhn "pythonic" means "idiomatic". The longer you use Python, the more natural you will find this syntax.Undulation
I know what ‘pythonic’ means. And I've been using Python continuously since 2014. I still don't find your answer natural.Springer
What makes it pythonic to construct an intermediate throw-away list?Unsavory
@Unsavory 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.Undulation
@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).Unsavory
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.Occur
@konpsych So does this one: new_a = a + [''] * (N - len(a))Unsavory
@Unsavory this is not the case for first when N < len(a). It is the case for the second answer you provided.Occur
True. I don't really like that answer either.Unsavory
@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"Addax
P
34

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, '', '', '', '']
Phosphoprotein answered 9/8, 2010 at 10:9 Comment(0)
J
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, '', '', '', '']
Juanitajuanne answered 22/8, 2017 at 18:38 Comment(1)
mit.take(N, mit.padnone(a)) returns a list by itself.Mayday
E
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 ) )
Emmerie answered 9/8, 2010 at 10:4 Comment(2)
I knew about izip_longest but resulting the code does not look nice =)Ashburn
I believe you mean operator.itemgetter(). Also the None values needed to be replaced with "".Juanitajuanne
R
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()
Repugnant answered 9/8, 2010 at 10:32 Comment(0)
H
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)
Hydraulics answered 3/1, 2011 at 21:34 Comment(1)
To say frankly, a+['']*(N-len(a)) looks much clearer. Besides, it lacks casting to list. But thank you anyway.Ashburn
S
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 ''.

Superstar answered 3/12, 2020 at 9:15 Comment(0)
P
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.

Pomeranian answered 17/4, 2019 at 20:16 Comment(2)
More concisely, a.extend((N-len(a))*[padding_value]) (I'm using OP notation).Intertidal
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.Pomeranian
O
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, '', '', '', '']
Ordinate answered 26/9, 2019 at 8:1 Comment(0)
M
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]
Moussaka answered 23/3, 2016 at 23:59 Comment(0)
N
3

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))
Nur answered 7/1, 2022 at 11:58 Comment(0)
F
1

Adding to the existing list with np.repeat:

import numpy as np
a + list(np.repeat([''], (N - len(a))))
Feeley answered 6/1, 2021 at 1:7 Comment(0)
G
-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 )]
Goulette answered 16/1, 2021 at 1:59 Comment(1)
There is too much indentation in the code block. It is also recommended to print the result after the operations. Other than that, it works.Mayday

© 2022 - 2024 — McMap. All rights reserved.