Padding ou tronquer une liste Python
j'aimerais tronquer ou tamponner une liste. Par exemple: pour la taille 4:
[1,2,3] -> [1,2,3,0]
[1,2,3,4,5] -> [1,2,3,4]
je peux voir un couple de façons:
def trp(l, n):
""" Truncate or pad a list """
r = l[:n]
if len(r) < n:
r.extend([0] * (n - len(r)))
return r
Ou un court, mais de moins en moins efficace:
map(lambda x, y: x if x else 0, m[0:n], [0] * n)
Est-il une façon plus élégante de le faire?
7 réponses
trancher en utilisant un index plus grand que la longueur d'une liste retourne juste la liste entière.
la Multiplication d'une liste par une valeur négative retourne une liste vide.
cela signifie Que la fonction peut être écrite comme suit:
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]: []
Vous pouvez utiliser itertools
module pour le rendre complètement paresseux, comme ceci
>>> 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]
ici, nous enchaînons la séquence réelle avec le répéteur infini avec le filler
valeur. Et puis on coupe l'itérateur enchaîné à size
.
Donc, si la séquence a moins d'éléments que size
,chain
va commencer à consommer le repeat
. Si la séquence a au moins size
, puis chain
n'aura même pas à utiliser le repeat
.
le principal avantage de cette méthode est que, la liste complète tronquée ou capitonnée n'est pas créée en mémoire, à moins qu'elle ne soit demandée. Donc, si tout ce que vous allez faire est de le parcourir, il vous suffit de le parcourir comme ceci
>>> for item in trimmer([1, 2, 3, 4, 5], 4):
... print(item * 2)
...
...
2
4
6
8
Ou, si vous voulez l'utiliser avec un autre ou garnis collier de liste, vous pouvez toujours le faire sans créer une liste réelle, comme ceci
>>> 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
La Paresse Des Roches ;-)
version en place:
l[n:] = [0] * (n - len(l))
version de la Copie:
l[:n] + [0] * (n - len(l))
Vous pouvez utiliser 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]
je pense que votre version d'origine est non seulement très simple mais aussi la plus efficace, posté jusqu'à présent. J'ai stocké toutes les réponses données ici dans des fichiers séparés (dont chacun exposant une fonction "trimmer") et les ai ensuite testées pour les deux capitonnage ainsi que la troncature. Voici les résultats:
$ python --version
Python 2.7.6
Padding une liste de 100 éléments de 200 éléments:
$ 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
la Troncation d'une liste de 100 éléments à 50 éléments:
$ 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
juste une solution insignifiante. 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]
ajouter -
ajouter des zéros jusqu'à ce que votre liste atteigne la longueur dont vous avez besoin:
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]
ignorez le None
s
In [33]: x
Out[33]: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
couper
Utilisation de l'épissage:
In [19]: x
Out[19]: [1, 2, 3, 0, 1, 2, 3, 4]
In [20]: x[:4]
Out[20]: [1, 2, 3, 0]