How to force a list to a fixed size?
I want to create a list that will contain the last 5 values entered into it.
Here is an example:
>>> 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) # only 5 items in list
['orange', 'grape', 'banana', 'mango', 'kiwi']
So, in Python, is there any way to achieve what is demonstrated above? The variable does not need to be a list, I just used it as an example.
You might want to use a collections.deque object with the maxlen
constructor argument instead:
>>> 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) # only 5 items in list
deque(['orange', 'grape', 'banana', 'mango', 'kiwi'], maxlen=5)
I ran into this same issue... maxlen=5 from deque was NOT a supported option due to access speed / reliability issues.
SIMPLE Solution:
l = []
l.append(x) # add 'x' to right side of list
l = l[-5:] # maxlen=5
After you append, just redefine 'l' as the most recent five elements of 'l'.
print(l)
Call it Done.
For your purposes you could stop right there... but I needed a popleft(). Whereas pop() removes an item from the right where it was just appended... pop(0) removes it from the left:
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
Hat tip to James at Tradewave.net
No need for class functions or deque.
Further... to append left and pop right:
l = []
l.insert(0, x) # l.appendleft(x)
l = l[-5:] # maxlen=5
Would be your appendleft() equivalent should you want to front load your list without using deque
Finally, if you choose to append from the left...
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
You could subclass list
>>> class L(list):
... def append(self, item):
... list.append(self, item)
... if len(self) > 5: del self[0]
...
>>> 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']
>>>
deque
is slow for random access and does not support slicing. Following on gnibbler's suggestion, I put together a complete list
subclass.
However, it is designed to "roll" right-to-left only. For example, insert()
on a "full" list will have no effect.
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()
You could use a capped collection in PyMongo - it's overkill, but it does the job nicely:
import pymongo
#create collection
db.createCollection("my_capped_list",{capped:True, max:5})
#do inserts ...
#Read list
l = list(db.my_capped_list.find())
Hence any time you call my_capped_list
, you will retrieve the last 5 elements inserted.
Most often when you need such a kind of facility, you would write a function which takes the list and then returns the last five elements.
>>> l = range(10)
>>> l[-5:]
But if you really want a custom list, having a cap on five elements, you can override the built-in list and it's methods, you would do something like this, for all it's methods.
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
It can be as simple as the below solution
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))
精彩评论