开发者

Some built-in to pad a list in python

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 mi开发者_如何学Cssed:

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


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, '')


I think this approach is more visual and pythonic.

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


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, '', '', '', '']


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, '', '', '', '']


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 ) )


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()


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)


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, '', '', '', '']


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]


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.


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 ''.


Adding to the existing list with np.repeat:

import numpy as np
a + list(np.repeat([''], (N - len(a))))


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))


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 )]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜