Slicing Lists and Tuples in Python: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(22 intermediate revisions by the same user not shown)
Line 3: Line 3:
* [[Python_Language_Tuple#Slices|Tuples]]
* [[Python_Language_Tuple#Slices|Tuples]]
=Overview=
=Overview=
'''Indexing''' means selecting elements from a list or a tuple using the index operator <code>[...]</code> and a single numeric index.


Slicing means extracting of a section of elements from of a list or a tuple, using the slice notation:
'''Slicing''' means extracting of a section of elements from of a list or a tuple, using the index operator <code>[...]</code> and the slice notation:


<font size=-2>
<font size=-2>
Line 10: Line 11:
</font>
</font>


The elements are selected as follows: start with the start index, and keep adding the step value to obtain the indices of the selected elements. Stop when the index value such computed is equal or larger than the end index. In case of a [[#Negative_Step|negative step]], stop if the index value such calculated is equal or smaller than the end index.
The elements are selected as follows: start with the start index, and keep adding the step value to obtain the indices of the selected elements. Stop when the index value such computed is equal or larger than the end index. In case of a [[#Negative_Step|negative step]], stop if the index value such calculated is equal or smaller than the end index. The end index is the index of the first element '''not included''' in the slice.
 
<font color=darkkhaki>The algorithm is incomplete, it does not account for the behavior shown in [[#Remove_the_Last_Element|Remove the Last Element]].</font>


=Start Index=
=Start Index=


The start index can be missing, and in that case is either 0 for a positive step, or <code>len - 1</code> for a negative step:
The start index can be missing, and in that case is either 0 for a positive step, or <code>len - 1</code> for a negative step:
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#    0    1    2    3    4    5    6    7
assert l[1:3] == ['b', 'c']
assert l[:3] == ['a', 'b', 'c']
assert l[:3:-1] == ['h', 'g', 'f', 'e']
</syntaxhighlight>
=End Index=
The end index can be missing, and in that case is either <code>len</code> for a positive step, or - 1 for a negative step:
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#    0    1    2    3    4    5    6    7
assert l[1:3] == ['b', 'c']
assert l[1:] == ['b', 'c', 'd', 'e', 'f', 'g', 'h']
assert l[1::-1] == ['b', 'a']
assert l[:] == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
</syntaxhighlight>


=Step=
=Step=
The steps represents the increment added to start index to obtain selected indexes. The elements are selected starting from the start index (inclusive) and then successively adding the <code>step</code> value to obtain the value of the selected indexes, until the index value is equal or larger than the end index.
The steps represents the increment added to start index to obtain selected indexes. The elements are selected starting from the start index (inclusive) and then successively adding the <code>step</code> value to obtain the value of the selected indexes, until the index value is equal or larger than the end index for positive steps, or equal or smaller than the end index for negative steps.


If the step is omitted, it defaults to 1. <code>[1:3]</code>, <code>[1:3:]</code> and <code>[1:3:1]</code> are equivalent and result in:
If the step is omitted, it defaults to 1. <code>[1:3]</code>, <code>[1:3:]</code> and <code>[1:3:1]</code> are equivalent and result in:
Line 25: Line 51:
#    0    1    2    3    4    5    6    7
#    0    1    2    3    4    5    6    7


l[1:3]   # ['b', 'c']
assert l[1:3] == ['b', 'c']
l[1:3:] # ['b', 'c']
assert l[1:3:] == ['b', 'c']
l[1:3:1] # ['b', 'c']
assert l[1:3:1] == ['b', 'c']
</syntaxhighlight>
</syntaxhighlight>


Line 35: Line 61:
#    0    1    2    3    4    5    6    7
#    0    1    2    3    4    5    6    7


l[1:6:2]   # ['b', 'd', 'f']
assert l[1:6:2] == ['b', 'd', 'f']
</syntaxhighlight>
</syntaxhighlight>


Line 43: Line 69:
#    0    1    2    3    4    5    6    7
#    0    1    2    3    4    5    6    7


l[6:3:-1]   # ['g', 'f', 'e']
assert l[6:3:-1] == ['g', 'f', 'e']
</syntaxhighlight>
</syntaxhighlight>
=Bare Slice=
<code>[:]</code> is called '''bare slice''' and represents the entire list.


=Reversing a List using a Slice=
=Slices Are Copies=
 
 


The indexing operator produces a copy of the underlying data. Modifying a slice does not modifies the original list:


--------
A sub-sequence of a list can be extracted with a slice. The slice <code>[<start-index>:<end-index>:<step>]</code> specified the index of the last element, and the index of the first element '''not included''' in slice, and the step. The step is optional, the default value is 1.
<syntaxhighlight lang='py'>
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c', 'd', 'e', 'f']
a = [1, 2, 3]
assert ['a', 'b', 'c', 'd', 'e', 'f'] == l[:] # starts from the beginning and ends after the end of the list
b = a[1:]
assert ['c', 'd'] == l[2:4]
b[0]=20
assert ['c'] == l[2:4:2]
b[1]=30
assert b == [20, 30]
assert a == [1, 2, 3]
</syntaxhighlight>
</syntaxhighlight>
The step can be negative, which means the slice starts at the end and goes from right to left.
 
=Well-Known Use Cases=
==Copy a List using a Slice==
<syntaxhighlight lang='py'>
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c', 'd', 'e', 'f']
l2 = l[:]
assert ['f', 'e', 'd', 'c', 'b', 'a'] == l[::-1]
</syntaxhighlight>
</syntaxhighlight>


<code>[:]</code> creates a copy of the list.
==Reverse a List using a Slice==
<syntaxhighlight lang='py'>
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c']
assert l[::-1] == ['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
l2 = l[:]
l2[0] = 'x'
assert ['a', 'b', 'c'] == l
assert ['x', 'b', 'c'] == l2
</syntaxhighlight>
</syntaxhighlight>
 
==Extract a Sub-List from a Certain Index==
Remove the last element of the list:
<syntaxhighlight lang='py'>
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c']
assert l[0:] == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
l2 = l[:-1]
assert l[1:] == ['b', 'c', 'd', 'e', 'f', 'g', 'h']
assert ['a', 'b'] == l2
assert l[2:] == ['c', 'd', 'e', 'f', 'g', 'h']
assert l[3:] == ['d', 'e', 'f', 'g', 'h']
assert l[4:] == ['e', 'f', 'g', 'h']
assert l[5:] == ['f', 'g', 'h']
assert l[6:] == ['g', 'h']
assert l[7:] == ['h']
assert l[8:] == []
</syntaxhighlight>
</syntaxhighlight>


===Extract Elements from the Tail of the List Starting with a Certain Index===
==Remove the Last Element==
<syntaxhighlight lang='py'>
<syntaxhighlight lang='py'>
l = [1, 2, 3]
assert l[:-1] == ['a', 'b', 'c', 'd', 'e', 'f', 'g']
assert l[0:] == [1, 2, 3]
assert l[1:] == [2, 3]
assert l[2:]== [3]
assert l[3:] == [] # empty list
assert l[4:] == [] # empty list
</syntaxhighlight>
</syntaxhighlight>
===Extract Elements from the Head of the List Counting from the Tail===
TODO

Latest revision as of 01:12, 21 May 2024

Internal

Overview

Indexing means selecting elements from a list or a tuple using the index operator [...] and a single numeric index.

Slicing means extracting of a section of elements from of a list or a tuple, using the index operator [...] and the slice notation:

[<start-index>:<end-index>:<step>]

The elements are selected as follows: start with the start index, and keep adding the step value to obtain the indices of the selected elements. Stop when the index value such computed is equal or larger than the end index. In case of a negative step, stop if the index value such calculated is equal or smaller than the end index. The end index is the index of the first element not included in the slice.

The algorithm is incomplete, it does not account for the behavior shown in Remove the Last Element.

Start Index

The start index can be missing, and in that case is either 0 for a positive step, or len - 1 for a negative step:

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#     0    1    2    3    4    5    6    7

assert l[1:3] == ['b', 'c']
assert l[:3] == ['a', 'b', 'c']
assert l[:3:-1] == ['h', 'g', 'f', 'e']

End Index

The end index can be missing, and in that case is either len for a positive step, or - 1 for a negative step:

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#     0    1    2    3    4    5    6    7

assert l[1:3] == ['b', 'c']
assert l[1:] == ['b', 'c', 'd', 'e', 'f', 'g', 'h']
assert l[1::-1] == ['b', 'a']
assert l[:] == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

Step

The steps represents the increment added to start index to obtain selected indexes. The elements are selected starting from the start index (inclusive) and then successively adding the step value to obtain the value of the selected indexes, until the index value is equal or larger than the end index for positive steps, or equal or smaller than the end index for negative steps.

If the step is omitted, it defaults to 1. [1:3], [1:3:] and [1:3:1] are equivalent and result in:

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#     0    1    2    3    4    5    6    7

assert l[1:3] == ['b', 'c']
assert l[1:3:] == ['b', 'c']
assert l[1:3:1] == ['b', 'c']

If the step has a value larger than 1, non-successive elements are selected:

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#     0    1    2    3    4    5    6    7

assert l[1:6:2] == ['b', 'd', 'f']

If the step has a negative value, the same algorithm applies: the interpreter starts with start index, keeps adding the step in a loop, which now is a negative value, so the iteration advances toward the beginning of the list, and stops when the resulted index is equal or smaller than the end index:

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
#     0    1    2    3    4    5    6    7

assert l[6:3:-1] == ['g', 'f', 'e']

Bare Slice

[:] is called bare slice and represents the entire list.

Slices Are Copies

The indexing operator produces a copy of the underlying data. Modifying a slice does not modifies the original list:

a = [1, 2, 3]
b = a[1:]
b[0]=20
b[1]=30
assert b == [20, 30]
assert a == [1, 2, 3]

Well-Known Use Cases

Copy a List using a Slice

l2 = l[:]

Reverse a List using a Slice

assert l[::-1] == ['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']

Extract a Sub-List from a Certain Index

assert l[0:] == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
assert l[1:] == ['b', 'c', 'd', 'e', 'f', 'g', 'h']
assert l[2:] == ['c', 'd', 'e', 'f', 'g', 'h']
assert l[3:] == ['d', 'e', 'f', 'g', 'h']
assert l[4:] == ['e', 'f', 'g', 'h']
assert l[5:] == ['f', 'g', 'h']
assert l[6:] == ['g', 'h']
assert l[7:] == ['h']
assert l[8:] == []

Remove the Last Element

assert l[:-1] == ['a', 'b', 'c', 'd', 'e', 'f', 'g']