Подтвердить что ты не робот

Заполнение или усечение списка Python

Я бы хотел усечь или заполнить список. Например. для размера 4:

[1,2,3] -> [1,2,3,0]
[1,2,3,4,5] -> [1,2,3,4]

Я вижу пару способов:

def trp(l, n):
    """ Truncate or pad a list """
    r = l[:n]
    if len(r) < n:
        r.extend([0] * (n - len(r)))
    return r

Или более короткий, но менее эффективный:

map(lambda x, y: x if x else 0, m[0:n], [0] * n)

Есть ли более элегантный способ сделать это?

4b9b3361

Ответ 1

Нарезка с использованием индекса, большего, чем длина списка, просто возвращает весь список.

Умножение списка на отрицательное значение возвращает пустой список.

Это означает, что функция может быть записана как:

def trp(l, n):
    return l[:n] + [0]*(n-len(l))

trp([], 4)
[0, 0, 0, 0]

trp([1,2,3,4], 4)
[1, 2, 3, 4]

trp([1,2,3,4,5], 4)
[1, 2, 3, 4]

trp([1,2,3], 4)
[1, 2, 3, 0]

In [1]: a = [1,2,3]

In [2]: a[:4]
Out[2]: [1, 2, 3]

In [3]: [0]*0
Out[3]: []

In [4]: [0]*-1
Out[4]: []

Ответ 2

Вы можете использовать модуль itertools, чтобы сделать его полностью ленивым, например

>>> from itertools import repeat, chain, islice
>>> def trimmer(seq, size, filler=0):
...     return islice(chain(seq, repeat(filler)), size)
... 
>>> list(trimmer([1, 2, 3], 4))
[1, 2, 3, 0]
>>> list(trimmer([1, 2, 3, 4, 5], 4))
[1, 2, 3, 4]

Здесь мы связываем фактическую последовательность с бесконечным ретранслятором со значением filler. И затем мы нарезаем цепочный итератор на size.

Итак, если если последовательность имеет меньшее количество элементов, чем size, chain начнет потреблять repeat. Если последовательность имеет не менее size элементов, тогда chain даже не придется использовать repeat.

Основным преимуществом этого метода является то, что полный обрезанный или заполненный список не создается в памяти, если только этого не требуется. Итак, если все, что вы собираетесь сделать, это перебрать его, то вы можете просто перебрать его так, как это.

>>> for item in trimmer([1, 2, 3, 4, 5], 4):
...     print(item * 2)
...     
... 
2
4
6
8

Или, если вы хотите использовать его с другим обрезанным или дополненным списком, вы все равно можете сделать это, не создавая фактический список, например этот

>>> for item in chain(trimmer([1, 2, 3], 4), trimmer([1, 2, 3, 4, 5], 4)):
...     print(item, item * 2)
...     
... 
1 2
2 4
3 6
0 0
1 2
2 4
3 6
4 8

Лестничные камни; -)

Ответ 3

In-place version:

l[n:] = [0] * (n - len(l))

Копировать версию:

l[:n] + [0] * (n - len(l))

Ответ 4

Я думаю, что ваша оригинальная версия не только очень проста, но и самая эффективная, опубликованная до сих пор. Я сохранил все ответы, приведенные здесь, в отдельных файлах (каждый из которых раскрывает функцию "триммер" ), а затем проверял их как для заполнения, так и для усечения. Вот результаты:

$ python --version
Python 2.7.6

Заполнение списка из 100 элементов до 200 элементов:

$ for VERSION in dmtri1 dmtri2 thefourtheye dting; do echo -n "$VERSION: "; python -m timeit -s "from $VERSION import trimmer; l = range(100)" -- 'list(trimmer(l, 200))'; done
dmtri1: 100000 loops, best of 3: 2.9 usec per loop
dmtri2: 10000 loops, best of 3: 27.1 usec per loop
thefourtheye: 100000 loops, best of 3: 5.78 usec per loop
dting: 100000 loops, best of 3: 2.69 usec per loop

Усечение списка из 100 элементов на 50 элементов:

$ for VERSION in dmtri1 dmtri2 thefourtheye dting; do echo -n "$VERSION: "; python -m timeit -s "from $VERSION import trimmer; l = range(100)" -- 'list(trimmer(l, 50))'; done
dmtri1: 1000000 loops, best of 3: 0.832 usec per loop
dmtri2: 100000 loops, best of 3: 8.27 usec per loop
thefourtheye: 100000 loops, best of 3: 2.62 usec per loop
dting: 1000000 loops, best of 3: 1.29 usec per loop

Ответ 5

Вы можете использовать numpy.pad:

>>> def trp(a,n):
...    diff=n-len(a)
...    if diff >0:
...         return np.lib.pad(l2,(0,diff),'constant', constant_values=(0))
...    else :
...         return a[:n]
... 

>>> l1=[1, 2, 3, 4, 5]
>>> l2=[1, 2, 3]
>>> trp(l2,4)
array([1, 2, 3, 0])
>>> trp(l1,4)
[1, 2, 3, 4]

Ответ 6

Добавить -

Добавьте нули до тех пор, пока ваш список не достигнет необходимой длины:

In [31]: x
Out[31]: [1, 2, 3, 0]

In [32]: [x.append(0) for i in range(10 - len(x))]
Out[32]: [None, None, None, None, None, None]

Игнорировать None s

In [33]: x
Out[33]: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]

Усечение

Использовать сплайсинг:

In [19]: x
Out[19]: [1, 2, 3, 0, 1, 2, 3, 4]

In [20]: x[:4]
Out[20]: [1, 2, 3, 0]

Ответ 7

Просто тривиальное решение. Unpythonic.

def f(a):
    length_a = len(a)
    limit = 4
    if length_a > limit:
      a = a[:limit]
    else:
      for i in xrange(0,limit - length_a):
        a.append(0)
    return a

>>> a = [1,2,3,4,5,6,7,7,8,8]
>>> b = [1]
>>> c = [1,2]
>>> f(a)
[1, 2, 3, 4]
>>> f(b)
[1, 0, 0, 0]
>>> f(c)
[1, 2, 0, 0]