Prev: Constructing lists       |       Next: List of lists

# List slicing¶

• List slicing is a technique for separating a list into parts, each of them being a sublist of the original list
• Sublists are new list objects in memory and not simply different 'views' of the original list
• Slicing notation is as follows:
  slice = alist[[start]:[end]:[step]]

where:
• 'start' is the index of the first element of the original list to be included in the slice
• 'end' is the index of the last element (NOT included in the slice)
• 'step' is the step for moving from start to end value
• Note that -as will become clear in the examples- none of the start, end, step arguments is absolutely necessary when slicing a list.
• Also, keep in mind that slicing is important in understanding the processing of more advanced Python data structures. So, it is worth investing some more time on the slicing topic to grasp both the concept and the implementation.
• Reflect on the examples below and make sure that you understand how slicing works
• Slice L1[0:5] below contains 5 items with indices from 0 to 4
In [4]:
L1 = [i for i in range(ord('A'), ord('K'))]
print(L1)

L2 = L1[0:5]
L2

[65, 66, 67, 68, 69, 70, 71, 72, 73, 74]

Out[4]:
[65, 66, 67, 68, 69]
• Slice spam[2:5] below contains 3 items: the 3rd, 4th and 5th item of the original list
In [16]:
spam = ['a','b','c','d','e']
spam2 = spam[2:5]
spam2

Out[16]:
['c', 'd', 'e']
• When 'start' values is missing, the value 0 is assumed
In [5]:
L1 = [2*i for i in range(-5,5)]
print(L1)

L2 = L1[:5]     # Note that ':' must be included to denote slicing instead of simple indexing
L2

[-10, -8, -6, -4, -2, 0, 2, 4, 6, 8]

Out[5]:
[-10, -8, -6, -4, -2]
• When 'end' value is missing, the value len() is assumed
• Therefore: the value len() is acceptable in slicing BUT NOT in indexing
In [10]:
L1 = [i+2 for i in range(-5,5)]
print(L1,'\t',len(L1),'\n')

L2 = L1[5:]
print(L2)
print('The same:',L1[5:10])

[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] 	 10

[2, 3, 4, 5, 6]
The same: [2, 3, 4, 5, 6]


### The 'step' value in slicing¶

• The 'step' value can be either positive or negative, depending on how 'start' and 'end' values are positioned
In [12]:
L1 = [x for x in range(10)]
print(L1)

L2 = L1[3:10:2]      # Note that the element with index '10' is NOT included in L2 slice
L2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Out[12]:
[3, 5, 7, 9]
• Below 'start' is greater than 'end'; so, 'step' needs to be negative for the slicing to work right
In [13]:
L1 = [x for x in range(10)]
L3 = L1[10:2:-3]
L3

Out[13]:
[9, 6, 3]
• If 'start' and 'end' are both missing then a copy of the original list is created
In [14]:
L1 = [x for x in range(10)]
L4 = L1[:]
L4

Out[14]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
• The 'step' defines how the index changes while slicing from 'start' to 'end'
In [15]:
L1 = [x for x in range(10)]
L5 = L1[::2]
L5

Out[15]:
[0, 2, 4, 6, 8]
• This slicing constructs a reverse copy of the original list. Do you see why?
In [16]:
L1 = [x for x in range(10)]
L6 = L1[::-1]
L6

Out[16]:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

### Negative indexes in slicing¶

• Negative indexes are acceptable in slicing as well.
• The last element of the list is considered to have index '-1'
In [17]:
L1 = [k for k in range(10)]
print(L1)
L2 = L1[-5:-1]
L2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Out[17]:
[5, 6, 7, 8]
In [19]:
L1 = [k for k in range(10)]
L3 = L1[-1:-len(L1):-1]
L3

Out[19]:
[9, 8, 7, 6, 5, 4, 3, 2, 1]
In [41]:
L0 = [x for x in range(1,12)]
L1 = [2*k for k in range(11)]
print(L0,'\t', L1)

L2 = [L1[-i::-1] for i in L0]
L2

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 	 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Out[41]:
[[20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0],
[18, 16, 14, 12, 10, 8, 6, 4, 2, 0],
[16, 14, 12, 10, 8, 6, 4, 2, 0],
[14, 12, 10, 8, 6, 4, 2, 0],
[12, 10, 8, 6, 4, 2, 0],
[10, 8, 6, 4, 2, 0],
[8, 6, 4, 2, 0],
[6, 4, 2, 0],
[4, 2, 0],
[2, 0],
[0]]

### Slicing and value assignment¶

• Combining slicing and assignment provides a flexible way to change and extend a list
• Note that in the following examples no new list is constructed but the items of the original list change (new values are assigned).
• Replace values in list: when the slice is of equal size with the list of new values.
In [85]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[0:3] = [101, 102, 103]     # Values 1,2,3 are replaced by 101, 102, 103
L1

Out[85]:
[101, 102, 103, 4, 5, 6, 7, 8, 9, 10]
• Replace and insert values: when the slice is smaller than the list of new values.
In [42]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[0:3] = [101, 102, 103, 104, 105]     # Values 1,2,3 are replaced and 104, 105 are inserted
L1

Out[42]:
[101, 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10]
• Replace and delete values: when the slice is bigger than the list of new values.
In [43]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[0:3] = [101,102]     # Values 1,2 are replaced but 3 is deleted
L1

Out[43]:
[101, 102, 4, 5, 6, 7, 8, 9, 10]
• Delete ONLY values: when slicing and assigning an empty list []
In [44]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[0:3] = []     # Values 1,2,3 are now simply deleted
L1

Out[44]:
[4, 5, 6, 7, 8, 9, 10]
• Insert ONLY new values: by indexing an 'insertion point' and assigning new values, these are only inserted (old values are intact)
• An insertion point is indexed when slicing indexes are equal: 'start' = 'end'
• Then the list of new values is inserted before item with index 'start'
In [45]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[1:1] = [101]     # Insertion point [1,1] is before element with index [1]
# The value 101 is inserted
L1

Out[45]:
[1, 101, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [46]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[0:0] = [101,102]     # Values 101,102 are inserted in the beginning
L1                      # What if we write: L1[:] = [101,102] - Why?

Out[46]:
[101, 102, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [47]:
L1 = [1,2,3,4,5,6,7,8,9,10]

L1[len(L1):] = [11, 12, 13]     # Extending the list with new values
L1

Out[47]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

See a table summarizing Python indexes and slices here

. Free learning material
. See full copyright and disclaimer notice