- 5.1 Introduction
- 5.2 Lists
- 5.3 Tuples
- 5.4 Unpacking Sequences
- 5.5 Sequence Slicing
- 5.6 del Statement
- 5.7 Passing Lists to Functions
- 5.8 Sorting Lists
- 5.9 Searching Sequences
- 5.10 Other List Methods
- 5.11 Simulating Stacks with Lists
- 5.12 List Comprehensions
- 5.13 Generator Expressions
- 5.14 Filter, Map and Reduce
- 5.15 Other Sequence Processing Functions
- 5.16 Two-Dimensional Lists
- 5.17 Intro to Data Science: Simulation and Static Visualizations
- 5.18 Wrap-Up
5.9 Searching Sequences
Often, you’ll want to determine whether a sequence (such as a list, tuple or string) contains a value that matches a particular key value. Searching is the process of locating a key.
List Method index
List method index takes as an argument a search key—the value to locate in the list—then searches through the list from index 0 and returns the index of the first element that matches the search key:
In [1]: numbers = [3, 7, 1, 4, 2, 8, 5, 6] In [2]: numbers.index(5) Out[2]: 6
A ValueError occurs if the value you’re searching for is not in the list.
Specifying the Starting Index of a Search
Using method index’s optional arguments, you can search a subset of a list’s elements. You can use *= to multiply a sequence—that is, append a sequence to itself multiple times. After the following snippet, numbers contains two copies of the original list’s contents:
In [3]: numbers *= 2 In [4]: numbers Out[4]: [3, 7, 1, 4, 2, 8, 5, 6, 3, 7, 1, 4, 2, 8, 5, 6]
The following code searches the updated list for the value 5 starting from index 7 and continuing through the end of the list:
In [5]: numbers.index(5, 7) Out[5]: 14
Specifying the Starting and Ending Indices of a Search
Specifying the starting and ending indices causes index to search from the starting index up to but not including the ending index location. The call to index in snippet [5]:
numbers.index(5, 7)
assumes the length of numbers as its optional third argument and is equivalent to:
numbers.index(5, 7, len(numbers))
The following looks for the value 7 in the range of elements with indices 0 through 3:
In [6]: numbers.index(7, 0, 4) Out[6]: 1
Operators in and not in
Operator in tests whether its right operand’s iterable contains the left operand’s value:
In [7]: 1000 in numbers Out[7]: False In [8]: 5 in numbers Out[8]: True
Similarly, operator not in tests whether its right operand’s iterable does not contain the left operand’s value:
In [9]: 1000 not in numbers Out[9]: True In [10]: 5 not in numbers Out[10]: False
Using Operator in to Prevent a ValueError
You can use the operator in to ensure that calls to method index do not result in ValueErrors for search keys that are not in the corresponding sequence:
In [11]: key = 1000 In [12]: if key in numbers: ...: print(f'found {key} at index {numbers.index(search_key)}') ...: else: ...: print(f'{key} not found') ...: 1000 not found
Built-In Functions any and all
Sometimes you simply need to know whether any item in an iterable is True or whether all the items are True. The built-in function any returns True if any item in its iterable argument is True. The built-in function all returns True if all items in its iterable argument are True. Recall that nonzero values are True and 0 is False. Non-empty iterable objects also evaluate to True, whereas any empty iterable evaluates to False. Functions any and all are additional examples of internal iteration in functional-style programming.