2011-05-10 15 views
42

En Python (3) Quiero crear una lista que contendrá las últimas 5 variables ingresadas en ella. Aquí se muestra un ejemplo:Python, forzando una lista a un tamaño fijo

>>>l = [] 
>>>l.append('apple') 
>>>l.append('orange') 
>>>l.append('grape') 
>>>l.append('banana') 
>>>l.append('mango') 
>>>print(l) 
['apple','orange','grape','banana','mango'] 
>>>l.append('kiwi') 
>>>print(l) 
['orange','grape','banana','mango','kiwi'] #only 5 items in list 

Así, en Python, ¿Hay alguna manera de lograr lo que se ha demostrado más arriba? La variable no necesita ser una lista, solo la utilicé como ejemplo.

Gracias!

Respuesta

77

Es posible que desee utilizar un objeto collections.deque con el argumento del constructor maxlen lugar:

>>>l = collections.deque(maxlen=5) 
>>>l.append('apple') 
>>>l.append('orange') 
>>>l.append('grape') 
>>>l.append('banana') 
>>>l.append('mango') 
>>>print(l) 
deque(['apple','orange','grape','banana','mango'], maxlen=5) 
>>>l.append('kiwi') 
>>>print(l) 
deque(['orange','grape','banana','mango','kiwi'], maxlen=5) #only 5 items in list 
+0

+1, agradable - Estaba a punto de sugerir lista de subclases ala [gnibbler] (http://stackoverflow.com/questions/ 5944708/python-forcing-a-list-to-a-fixed-size/5944763 # 5944763) pero sospeché que podría haber una solución preconstruida. – senderle

+0

¿Cómo implementa python la solución? ¿Deque aparece el elemento a la izquierda cuando se agrega un nuevo elemento? –

+0

Python tiene una gran cantidad de estructuras de datos de listas que pueden convertirse en una lista cuando las necesite utilizando list(). Por ejemplo, haz una lista de dict y try (MyDict). –

10

Usted podría subclase list

>>> class L(list): 
...  def append(self, item): 
...   list.append(self, item) 
...   if len(self) > 5: self[:1]=[] 
... 
>>> l = L() 
>>> l.append('apple') 
>>> l.append('orange') 
>>> l.append('grape') 
>>> l.append('banana') 
>>> l.append('mango') 
>>> print(l) 
['apple', 'orange', 'grape', 'banana', 'mango'] 
>>> l.append('kiwi') 
>>> print(l) 
['orange', 'grape', 'banana', 'mango', 'kiwi'] 
>>> 
+1

También necesitaría extender los métodos 'insert',' extend' y 'setitem' (' l [1: 1] = range (100) ') para que esto sea infalible. –

+0

Considera 'del self [0]'. – Alfe

+0

y tal vez necesite anular '__add__' también – Lee

-1

mayoría de las veces cuando se necesita un tipo de instalación de este tipo, lo haría escriba una función que tome la lista y luego devuelva los últimos cinco elementos.

>>> l = range(10) 
>>> l[-5:] 

Pero si realmente quieres una lista personalizada, que tiene un tapón en cinco elementos, puede anular la lista incorporada y es métodos, deberías hacer algo como esto, para todos sus métodos.

class fivelist(list): 
    def __init__(self, items): 
     list.__init__(self, items[-5:]) 

    def insert(self, i, x): 
     list.insert(self, i, x) 
     return self[-5:] 

    def __getitem__(self, i): 
     if i > 4: 
      raise IndexError 
     return list.__getitem__(self, i) 

    def __setitem__(self, i, x): 
     if 0<= i <= 4: 
      return list.__setitem__(self, i, x) 
     else: 
      raise IndexError 
+0

La razón por la que no puedo usar una función que devuelve parte de la lista es porque la lista con el tiempo se volverá MUY grande y tendrá muchos datos inútiles que nunca ser usado nuevamente – lanrat

+0

Eso puede ser controlado nuevamente por la función. si el crecimiento es grande, elimine los que están al principio. –

+0

El 'return' en' insert() 'no tiene sentido, porque' list.insert' está destinado a funcionar in situ. – glglgl

5

deque es lenta para el acceso aleatorio y no es compatible con el corte en lonchas. Siguiendo la sugerencia de gnibbler, armé una subclase list completa.

Sin embargo, está diseñado para "rodar" de derecha a izquierda solamente. Por ejemplo, insert() en una lista "completa" no tendrá ningún efecto.

class LimitedList(list): 

    # Read-only 
    @property 
    def maxLen(self): 
     return self._maxLen 

    def __init__(self, *args, **kwargs): 
     self._maxLen = kwargs.pop("maxLen") 
     list.__init__(self, *args, **kwargs) 

    def _truncate(self): 
     """Called by various methods to reinforce the maximum length.""" 
     dif = len(self)-self._maxLen 
     if dif > 0: 
      self[:dif]=[] 

    def append(self, x): 
     list.append(self, x) 
     self._truncate() 

    def insert(self, *args): 
     list.insert(self, *args) 
     self._truncate() 

    def extend(self, x): 
     list.extend(self, x) 
     self._truncate() 

    def __setitem__(self, *args): 
     list.__setitem__(self, *args) 
     self._truncate() 

    def __setslice__(self, *args): 
     list.__setslice__(self, *args) 
     self._truncate() 
6

Me encontré con este mismo problema ... maxlen = 5 de deque NO era una opción compatible debido a problemas de velocidad/fiabilidad de acceso.

solución simple:

l = [] 
l.append(x)       # add 'x' to right side of list 
l = l[-5:]       # maxlen=5 

Después de añadir, simplemente redefinir 'l' como los más recientes cinco elementos de 'L'.

print(l) 

Llámalo Hecho.

Para sus propósitos, podría detenerse allí ... pero necesitaba un popleft(). Mientras que el pop() elimina un elemento de la derecha donde estaba anexa ... pop (0) elimina de la izquierda:

if len(l) == 5:      # if the length of list 'l' has reached 5 
    right_in_left_out = l.pop(0) # l.popleft() 
else:        # 
    right_in_left_out = None  # return 'None' if not fully populated 

Sombrero de punta a James en Tradewave.net

No hay necesidad de funciones de clase o deque.

Más ... para anexar izquierda y derecha pop:

l = [] 
l.insert(0, x)      # l.appendleft(x) 
l = l[-5:]       # maxlen=5 

sería su equivalente appendleft() en caso de que desee cargar su lista frontal sin utilizar deque

Por último, si decide anexar desde la izquierda ...

if len(l) == 5:      # if the length of list 'l' has reached 5 
    left_in_right_out = l.pop()  # pop() from right side 
else:        # 
    left_in_right_out = None  # return 'None' if not fully populated 
-3

Puede ser tan simple como la solución a continuación

lst = [] 
arr_size = int(input("Enter the array size ")) 
while len(lst) != arr_size: 
    arr_elem= int(input("Enter the array element ")) 
    lst.append(arr_elem) 

sum_of_elements = sum(lst) 

print("Sum is {0}".format(sum_of_elements)) 
Cuestiones relacionadas