Slices index python - 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.

Related

How to know when to refer an item in a for loop by itself vs. referring to an item as an index of the list

In a for loop, I'm trying to understand when to refer to an item by its item name and when to refer to the item as an index of the list I'm looping through.
In the code pasted below, I don't understand why "idx" is referred to in the "if" statement with a reference to the list index but then in the definition of maximum_score_index, it is referred to by itself.
def linear_search(search_list):
maximum_score_index = None
for **idx** in range(len(search_list)):
if not maximum_score_index or **search_list[idx]** > search_list[maximum_score_index]:
maximum_score_index = **idx**
return maximum_score_index
I'd love to have an explanation so I can differentiate in the future and some examples to show the difference so I can understand.
In Python, range(num) (more or less) returns a list of numbers from 0 through num - 1. It follows that range(len(my_list)) will generate a list of numbers from 0 through the length of my_list minus one. This is frequently useful, because the generated numbers are the indices of each item in my_list (Python lists start counting at 0). For example, range(len(["a", "b", "c"])) is [0, 1, 2], the indices needed to access each item in the original list. ["a", "b", "c"][0] is "a", and so on.
In Python, the for x in mylist loop iterates through each item in mylist, setting x to the value of each item in order. One common pattern for Python for loops is the for x in range(len(my_list)). This is useful, because you loop through the indices of each list item instead of the values themselves. It's almost as easy to access the values (just use my_list[x]) but it's much easier to do things like access the preceding value (just use my_list[x-1], much simpler than it would be if you didn't have the index!).
In your example, idx is tracking the index of each list item as the program iterates through search_list. In order to retrieve values from search_list, the program uses search_list[idx], much like I used my_list[x] in my example. The code then assigns maximum_score_index to the index itself, a number like 0, 1, or 2, rather than the value. It's still easy to find out what the maximum score is, with search_list[maximum_score_index]. The reason idx is not being used as a list accessor in the second case is because the program is storing the index itself, not the value of the array at that index.
Basically, this line:
if not maximum_score_index or **search_list[idx]** > search_list[maximum_score_index]:
maximum_score_index = **idx**
Can be thought of as:
if (this is the first pass) or (element at index > this loop-iteration element):
keep this index as largest element
What I recommend to do:
Go through the code, on a piece of paper and iterate over a list to
see what the code does
Write the code in any IDE, and use a debugger
to see what the code does
Are you looking for the index of the highest element in the list or the value?
If you are looking for the value, it can be as simple as:
highest = max(search_list)
You could also use enumerate, which will grant you "free" access to the current index in the loop:
>>> search_list
[10, 15, 5, 3]
>>> maximum_score_index = None
>>> for idx, value in enumerate(search_list):
... if not maximum_score_index or search_list[idx] > value:
... maximum_score_index = idx
...
>>> maximum_score_index
1
>>> search_list[maximum_score_index]
15

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

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'

How to get item's position in a list of list?

I don't know how to get certain items' position in a list of list.
list = [[1,2,3],[4,5,6],[7,8,9]]
if I want to get the position of '4' in the list,
the result should be like this.
list[1][0]
Or other expressions .
Thank you
for i,l in enumerate(list):
if 4 in l:
print "list[" + i + "][" + l.index(4) + "]"
Just try the first list. If at first you don't succeed, try, try again:
def indices(xss,x):
for i,xs in enumerate(xss):
try:
return i,xs.index(x)
except ValueError:
continue
raise ValueError
For example,
>>> x = [[1,2,3],[4,5,6],[7,8,9]]
>>> indices(x,4)
(1, 0)
By the way -- you should avoid calling a list variable list, since that is the name of a built-in.
If you are trying to ask how to index items from a matrix (2D list), then imagine your list like this.
[a,b,c]
a = [ 1 , 2 , 3 ]
b = [ 4 , 5 , 6 ]
c = [ 7 , 8 , 9 ]
To access any number, you want to access the sublist it is in (ie a or b or c first then access which item this is in the sublist you have chosen).
Let's say I want the number four. Four is in the second list, which is one index away from the first index, so we access this entire list with list[1]. However, we want the first element of this list, which is zero elements away from the first element, so we would access this as a[0], but in this case a is list[1], so overall the statement you would want to write would be:
list[1][0]
Another example would be if you wanted to get the number 3. 3 is in the sublist list[0], which we can imagine is named a, and if we wanted to access 3 from a we would type a[2]. However, in this case, we don't have a list 'a' but instead a list named list[0], so we would type:
list[0][2].
Hope this helps!
Update:
Here is a simple python solution. It checks if a four is in each sub-list in the matrix my_list.
for sub_list in my_list:
if 4 in sub_list:
print(my_list.index(sub_list),sub_list.index(4))

extract from a list of lists

How can I extract elements in a list of lists and create another one in python. So, I want to get from this:
all_list = [['1 2 3 4','2 3 4 5'],['2 4 4 5', '3 4 5 5' ]]
a new list like this:
list_of_lists = [[('3','4'),('4','5')], [('4','5'),('5','5')]]
Following is what I did, and it doesn't work.
for i in xrange(len(all_lists)):
newlist=[]
for l in all_lists[i]:
mylist = l.split()
score1 = float(mylist[2])
score2 = mylist[3]
temp_list = (score1, score2)
newlist.append(temp_list)
list_of_lists.append(newlist)
Please help. Many thanks in advance.
You could use a nested list comprehension. (This assumes you want the last two "scores" out of each string):
[[tuple(l.split()[-2:]) for l in list] for list in all_list]
It could work almost as-is if you filled in the value for mylist -- right now its undefined.
Hint: use the split function on the strings to break them up into their components, and you can fill mylist with the result.
Hint 2: Make sure that newlist is set back to an empty list at some point.
Adding to eruciforms answer.
First remark, you don't need to generate the indices for the all_list list. You can just iterate over it directly:
for list in all_lists:
for item in list:
# magic stuff
Second remark, you can make your string splitting much more succinct by splicing the list:
values = item.split()[-2:] # select last two numbers.
Reducing it further using map or a list comprehension; you can make all the items a float on the fly:
# make a list from the two end elements of the splitted list.
values = [float(n) for n in item.split()[-2:]]
And tuplify the resulting list with the tuple built-in:
values = tuple([float(n) for n in item.split()[-2:]])
In the end you can collapse it all to one big list comprehension as sdolan shows.
Of course you can manually index into the results as well and create a tuple, but usually it's more verbose, and harder to change.
Took some liberties with your variable names, values would tmp_list in your example.

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