There is: negative indices:
lst[-2]
Answer from Scott Hunter on Stack Overflowpython accessing the second to the last element in a list - Stack Overflow
python - Find the second last number from a list - Stack Overflow
python - How do I get the last element of a list? - Stack Overflow
python - How to get the second to last value in a list? - Stack Overflow
edit: forgot to mention I want the indeces not just the items
the methods I can think of are:
for i in range(len(arr) - 1)
for i, e in enumerate(arr[:len(arr) - 1])
I know range(len(arr)) is frowned upon, but I don't see how it's worse than enumerate in this case. In fact using enumerate on a shortened list and calling len to find the second to last element of that list seems extremely clunky and far less readable.
What's the best practice for doing this?
The Python slice syntax is alist[start:end:step]. So, with your slice ::-1, you are just reversing the list.
If you want the second element to the last, the correct slice would be
alist[1:]
a = {}
for line in file_a.readlines():
split_line = line.strip().split('\t')
a[split_line[0]] = split_line[1:]
a = {}
for line in file_a:
split_line = line.strip().split('\t')
a[split_line[0]] = split_line[1:]
You slicing expression split_line[::-1] evaluates to split_line reversed, because the third parameter is the step (-1 in this case). You want to start at element 1 and go all the way to the end, with the default step of 1. Check this answer for more on slice notation.
some_list[-1] is the shortest and most Pythonic.
In fact, you can do much more with this syntax. The some_list[-n] syntax gets the nth-to-last element. So some_list[-1] gets the last element, some_list[-2] gets the second to last, etc, all the way down to some_list[-len(some_list)], which gives you the first element.
You can also set list elements in this way. For instance:
>>> some_list = [1, 2, 3]
>>> some_list[-1] = 5 # Set the last element
>>> some_list[-2] = 3 # Set the second to last element
>>> some_list
[1, 3, 5]
Note that getting a list item by index will raise an IndexError if the expected item doesn't exist. This means that some_list[-1] will raise an exception if some_list is empty, because an empty list can't have a last element.
If your str() or list() objects might end up being empty as so: astr = '' or alist = [], then you might want to use alist[-1:] instead of alist[-1] for object "sameness".
The significance of this is:
alist = []
alist[-1] # will generate an IndexError exception whereas
alist[-1:] # will return an empty list
astr = ''
astr[-1] # will generate an IndexError exception whereas
astr[-1:] # will return an empty str
Where the distinction being made is that returning an empty list object or empty str object is more "last element"-like then an exception object.
It's simply a matter of iterating over the list and reporting list[n-1] when list[n]>my_limit.
You will need to extend this to cope with edge cases (i.e. this will error if the first value is over the limit etc.)
And you might want to split your list into one list per commodity as this will trigger when commodities change too.
my_limit = 0.2
for n in range(1, len(my_list)):
value = float(my_list[n][2].replace(",", "."))
prev_value = float(my_list[n-1][2].replace(",", "."))
if value > my_limit and prev_value < my_limit:
print(my_list[n-1])
you can use the itertools module for this
>>> import itertools
>>> my_list = [
['Morocco', 'Fish', '0,012'],
['Morocco', 'Fish', '0,153'],
['Morocco', 'Fish', '0,114'],
['Morocco', 'Fish', '0,109'],
['Morocco', 'Fish', '0,252'],
['Spain', 'Fish', '0,012'],
['Spain', 'Fish', '0,113'],
['Spain', 'Fish', '0,116'],
['Spain', 'Fish', '0,250'],
['Spain', 'Fish', '0,266'],
['Italy', 'Fish', '0,112'],
['Italy', 'Fish', '0,025'],
['Italy', 'Fish', '0,224'],
['Italy', 'Fish', '0,256'],
['Italy', 'Fish', '0,245']]
>>> my_limit = 0.2
>>> for key,sublists in itertools.groupby(my_list,lambda y:y[0]):
v=[] #we initialize it in case no element fulfill the condition
for v in itertools.takewhile(lambda x:float(x[-1].replace(",","."))<my_limit ,sublists):
pass
if v:
print(v,"->",v[-1])
['Morocco', 'Fish', '0,109'] -> 0,109
['Spain', 'Fish', '0,116'] -> 0,116
['Italy', 'Fish', '0,025'] -> 0,025
>>>
here with groupby we, well, group together all the consecutive sublist that have the same value in a given position we specify, which in this case is the first position, then we go into those sublist and take those that fulfill our condition and stop at the first that doesn't with takewhile and from those we only want the last one which will stored into v at the end of the loop.
I make that grouping because that make more sense to my, but if grouping like that isn't necessary, we can also use groupby to split the list into the subsection that fulfill the condition and those that do not by changing the grouping key
>>> my_list = [
['Morocco', 'Fish', '0,012'],
['Morocco', 'Fish', '0,153'],
['Morocco', 'Fish', '0,114'],
['Morocco', 'Fish', '0,109'],
['Morocco', 'Fish', '0,252'],
['Morocco', 'Fish', '0,002'],#extra
['Morocco', 'Fish', '0,252'],#extra
['Spain', 'Fish', '0,012'],
['Spain', 'Fish', '0,113'],
['Spain', 'Fish', '0,116'],
['Spain', 'Fish', '0,250'],
['Spain', 'Fish', '0,266'],
['Spain', 'Fish', '0,066'], #extra
['Spain', 'Fish', '0,366'], #extra
['Italy', 'Fish', '0,112'],
['Italy', 'Fish', '0,025'],
['Italy', 'Fish', '0,224'],
['Italy', 'Fish', '0,256'],
['Italy', 'Fish', '0,245'],
['Italy', 'Fish', '0,005'],#extra
['Italy', 'Fish', '0,305']]#extra
>>> for condition,sublist in itertools.groupby(my_list,lambda x:float(x[-1].replace(",","."))<my_limit):
if condition:
for v in sublist:
pass
print(v,"->",v[-1])
['Morocco', 'Fish', '0,109'] -> 0,109
['Morocco', 'Fish', '0,002'] -> 0,002
['Spain', 'Fish', '0,116'] -> 0,116
['Spain', 'Fish', '0,066'] -> 0,066
['Italy', 'Fish', '0,025'] -> 0,025
['Italy', 'Fish', '0,005'] -> 0,005
>>>