whats the use of [-1] and [0] here? - python

I would like to know whats the use of [-1] and [0] here. I also tried [1] in the first split and still working the same.
symbols = ["Wiki/ADBE.4", "Wiki/ALGN.4"]
clean_symbols = []
for symbol in symbols:
symbol = symbol.split("Wiki/")[-1].split(".4")[0]
print(symbol)
clean_symbols.append(symbol)
print(clean_symbols)
Thanks!

It's just indexing in lists. Let's look at how it works:
>>> symbol = "Wiki/ADBE.4" # this happens in the for loop
>>> symbol.split("Wiki/")
['', 'ADBE.4']
We have got two items in a list, created by split. Lists are indexed from 0, so 1 is "second item" and -1 is "the last item". In this case, this is the same item, so it works for both 1 and -1. But it really works that way only because you have a list with two items:
>>> symbol.split("Wiki/")[-1]
'ADBE.4'
>>> symbol.split("Wiki/")[1]
'ADBE.4'
If you had more, it would not be the same result:
>>> x = ['first', 'second', 'third']
>>> x[-1]
'third'
>>> x[1]
'second'
And then the same thing happens for the new string we got. A list and then an index picking the first item:
>>> symbol.split("Wiki/")[-1].split(".4")
['ADBE', '']
>>> symbol.split("Wiki/")[-1].split(".4")[0]
'ADBE'
And that's all the magic.

split creates a list. The rest is just list indexing. Negative index numbers count from the end, so [-1] is the last element of the list created by the first split. The next [0] index means the first element of the list created by the second split (just like it does in almost all languages).
Since [-1] and [1] work the same way, it probably means that your list has exactly 2 elements, so its last (-1) element is the same as its second ([1]).

For first iteration, split returns a list of which we are interested in the last element. Hence [-1]
symbol.split("Wiki/") returns ['', 'ADBE.4']
symbol.split("Wiki/")[-1] returns 'ADBE.4'
Hence, the second split returns a list of which we need the first element, hence [0]
'ADBE.4'.split('.4') returns ['ADBE','']
'ADBE.4'.split('.4')[0] returns 'ADBE'

Related

Tuple fails to print index if the item is repeated more than once

I am learning Python3 and I'm in tuples chapter now.
While we can use index method to print the place of an item like this:
>>> tup = ('a','b','a','c')
>>> tup.index('c')
>>> 3
But when I try to print the index for repeated item, it only prints for the first item and simply ignore the second one.
>>> tup.index('a')
0
I am expecting tuple to print both index (location).
Expected output
>>> tup.index('a')
0, 2
May I know why tuple having this behaviour? what if if we want to print the index for the repeated item in the tuple?
tuple.index is actually a three-argument function: tuple.index(x, start, end). It finds the first element equal to x in the range tuple[start:end]. It's just that by default start = 0 and end = len(t).
If you want the index of the second element you can do:
>>> i = tup.index('a')
>>> tup.index('a', i + 1)
2
If you want all indices you can use a list comprehension like L3viathan suggests.
Because that's what tuple.index does:
>>> help(tup.index)
index(...)
T.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
If you want all indices, you can make a list comprehension:
indices = [i for i, val in enumerate(tup) if val == 'c']
You can also do this with numpy.argwhere
https://docs.scipy.org/doc/numpy/reference/generated/numpy.argwhere.html
import numpy as np
np.argwhere(tup == 'a')

getting last element of a list of unknown size using slices

Let's say I have a list of unknown size, then I can access the last element using:
>>> l = list(range(10))
>>> l[-1]
9
However, is there any way to do this via a slice object like
>>> s = slice(-1, 10)
>>> l[s]
[9]
without knowing the length of my list?
Edit:
I simplified my Question a bit. I am fine with getting a list back, since I am iterating over the sublist later. I just needed a way of getting the last item of list besides being able to get every second element and so on ...
Yes, just use None as the end argument:
In [53]: l[slice(-1, None)]
Out[53]: [9]
This will of course produce a list [9], rather than the 9 in your question, because slicing a list always produces a sublist rather than a bare element.
If your objective is to pass arguments which you can use to index a list, you can use operator.itemgetter:
from operator import itemgetter
L = range(10)
itemgetter(-1)(L) # 9
In my opinion, for this specific task, itemgetter is cleaner than extracting a list via a slice, then extracting the only element of the list.
Note also that this works on a wider range of objects than just lists, e.g. with range as above.
If you were to access the last element of the list:
n = int(input())
user_input = [int(input) for i in range(n)]
last_element = user_input[-1]
Here we have used negative indices concept in lists.

Slices index python

Why when I run
>>> lista = [1,2,3,4,5]
>>> newl = [8,10]
>>> lista[1:4] = newl
[1,8,10,5]
The indexes for replaced values are between 1 until 3. And when I run.
>>> lista[2:2] = newl
[1,2,8,10,3,4,5]
A new index is created to save newl.
To understand slicing, you need to understand this.
Let's say
hi = "Hello"
The slice hi[1:2] contains "e". It starts at the second character and ends before the third. hi[2:2] contains nothing, because it starts at the third character and ends before the third character.
If you are inserting something between characters, it is replacing it. If you do:
hi[1:3] = "abcd"
Then "abcd" is replacing "el". This is the same with lists.
Slice indexes are start-inclusive and end-exclusive.
mylist[1:4] contains the elements at indexes 1, 2, and 3.
From http://docs.python.org/2/library/stdtypes.html:
The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j.
So if you get mylist[2:2] you are retrieving elements for which 2 <= k < 2 (no elements).
However, the list slicing syntax is clever enough to let you assign into that space, and insert elements into that position. If you run
mylist[2:2] = [5,6,7]
then you are inserting element into that space before index 2 that currently holds no elements.
In the first case you tell python to replace 3 specific elements in lista with other 2 elements from newl.
In the second case you reinitialize lista, then you select for substitution lista[2:2] that is an empty list ([]), and more precisely the empty list before the 3rd element of the list (whose index is 2) and so you replace this empty list with the two values from newl.

Get last item from a list as integer/float

Very simple question, I have a list like so:
a = [0,1,2,3,4,5,7,8]
and I need to get the last item in that list as a float or an integer. If I do:
print a[0], a[4]
I get 1 5, which is fine, but if i try to retrieve the last item with:
print a[-1:]
I get the list [8] instead of the number 8. I know that I could just use print a[len(a)-1] but it feels kind of overkill and now I also have the doubt of why is a[-1:] returning a list instead of an element?
You need to do a[-1] to get the last item. See below:
>>> a = [0,1,2,3,4,5,7,8]
>>> a[-1]
8
>>>
Having the colon in there makes it slice the list, not index it.
Here are some references on lists and slicing/indexing them:
http://docs.python.org/2/tutorial/introduction.html#lists
Explain Python's slice notation
Just do:
>>> a = [0,1,2,3,4,5,7,8]
>>> a[-1]
8
You were slicing the list not getting last item.
Simplest way:
>>> a = [0,1,2,3,4,5,7,8]
>>> a[-1]
8
why is a[-1:] returning a list instead of an element?
>>> list[-1:] # returns list
[8]
>>> list[-1] # returns value
8
we also can use pop(). But it removes last element from the list.So it depends what you want to do.
list.pop()

Extract certain elements from a list

I have no clue about Python and started to use it on some files. I managed to find out how to do all the things that I need, except for 2 things.
1st
>>>line = ['0', '1', '2', '3', '4', '5', '6']
>>>#prints all elements of line as expected
>>>print string.join(line)
0 1 2 3 4 5 6
>>>#prints the first two elements as expected
>>>print string.join(line[0:2])
0 1
>>>#expected to print the first, second, fourth and sixth element;
>>>#Raises an exception instead
>>>print string.join(line[0:2:4:6])
SyntaxError: invalid syntax
I want this to work similar to awk '{ print $1 $2 $5 $7 }'. How can I accomplish this?
2nd
how can I delete the last character of the line? There is an additional ' that I don't need.
Provided the join here is just to have a nice string to print or store as result (with a coma as separator, in the OP example it would have been whatever was in string).
line = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
print ','.join (line[0:2])
A,B
print ','.join (line[i] for i in [0,1,2,4,5,6])
A,B,C,E,F,G
What you are doing in both cases is extracting a sublist from the initial list. The first one use a slice, the second one use a list comprehension. As others said you could also have accessed to elements one by one, the above syntaxes are merely shorthands for:
print ','.join ([line[0], line[1]])
A,B
print ','.join ([line[0], line[1], line[2], line[4], line[5], line[6]])
A,B,C,E,F,G
I believe some short tutorial on list slices could be helpfull:
l[x:y] is a 'slice' of list l. It will get all elements between position x (included) and position y (excluded). Positions starts at 0. If y is out of list or missing, it will include all list until the end. If you use negative numbers you count from the end of the list. You can also use a third parameter like in l[x:y:step] if you want to 'jump over' some items (not take them in the slice) with a regular interval.
Some examples:
l = range(1, 100) # create a list of 99 integers from 1 to 99
l[:] # resulting slice is a copy of the list
l[0:] # another way to get a copy of the list
l[0:99] # as we know the number of items, we could also do that
l[0:0] # a new empty list (remember y is excluded]
l[0:1] # a new list that contains only the first item of the old list
l[0:2] # a new list that contains only the first two items of the old list
l[0:-1] # a new list that contains all the items of the old list, except the last
l[0:len(l)-1] # same as above but less clear
l[0:-2] # a new list that contains all the items of the old list, except the last two
l[0:len(l)-2] # same as above but less clear
l[1:-1] # a new list with first and last item of the original list removed
l[-2:] # a list that contains the last two items of the original list
l[0::2] # odd numbers
l[1::2] # even numbers
l[2::3] # multiples of 3
If rules to get items are more complex, you'll use a list comprehension instead of a slice, but it's another subjet. That's what I use in my second join example.
You don't want to use join for that. If you just want to print some bits of a list, then specify the ones you want directly:
print '%s %s %s %s' % (line[0], line[1], line[4], line[6])
Assuming that the line variable should contain a line of cells, separated by commas...
You can use map for that:
line = "1,2,3,4,5,6"
cells = line.split(",")
indices=[0,1,4,6]
selected_elements = map( lambda i: cells[i], indices )
print ",".join(selected_elements)
The map function will do the on-the-fly function for each of the indices in the list argument. (Reorder to your liking)
You could use the following using list comprehension :
indices = [0,1,4,6]
Ipadd = string.join([line[i] for i in xrange(len(line)) if i in indices])
Note : You could also use :
Ipadd = string.join([line[i] for i in indices])
but you will need a sorted list of indices without repetition of course.
Answer to the second question:
If your string is contained in myLine, just do:
myLline = myLine[:-1]
to remove the last character.
Or you could also use rstrip():
myLine = myLine.rstrip("'")
>>> token = ':'
>>> s = '1:2:3:4:5:6:7:8:9:10'
>>> sp = s.split(token)
>>> token.join(filter(bool, map(lambda i: i in [0,2,4,6] and sp[i] or False, range(len(sp)))))
'1:3:5:7'
l = []
l.extend(line[0:2])
l.append(line[5]) # fourth field
l.append(line[7]) # sixth field
string.join(l)
Alternatively
"{l[0]} {l[1]} {l[4]} {l[5]}".format(l=line)
Please see PEP 3101 and stop using the % operator for string formatting.

Categories

Resources