Заполнение или усечение списка 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)
Есть ли более элегантный способ сделать это?
Ответы
Ответ 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]