07. Lists, Arrays, and Sequential Data

A practical guide to storing, accessing, traversing, searching, and modifying ordered collections while avoiding common indexing and boundary errors.

Collections, Elements, and Positions

A collection lets a program keep related values under one name instead of creating a separate variable for every value. A list is an ordered sequence of elements, and an is another common name for a similar structure.

For example, a collection of scores can contain the values 8282, 9595, and 7171. The collection has one identity, while each score remains a separate element. This organization reduces repeated code and makes it easier to process many values with the same algorithm.

Positions and boundaries

An identifies an element's position. In zero-based indexing, the first element has 00, the second has 11, and so on. For a collection with length nn, the usual valid indexes are

0,1,2,…,n−10, 1, 2, \ldots, n-1

The length counts elements; it is not itself usually a valid . Thus, a collection of length 44 has last valid 33. Attempting to access 44 is an out-of-range access in many languages.

Some languages provide negative indexes. In Python, for example, −1-1 refers to the final element.

Takeaway: Think of length as a count and an as a position. In a zero-based collection, the last position is one less than the length.

Creating and Modifying Collections

A collection may begin with values or may begin empty. An existing element can be replaced by assigning a new value to its . Replacing an element normally changes the value at that position without changing the collection's length.

Common collection operations include:

  • Append: add an element at the end.

  • Insert: add an element at a specified position.

  • Remove: delete an element by value or position.

  • Clear: delete all elements.

The operation names and exact behavior vary by language. For example, Python provides operations including append, insert, remove, pop, and clear.

Reading versus changing

When a program only reads values, a value-based loop is often sufficient. When it must assign a replacement back into the collection, it generally needs an . Updating every negative value to zero, for example, requires identifying each element's position before assigning the replacement.

Changing an existing collection is . Creating a separate result collection preserves the original data. This distinction matters when multiple variables refer to the same collection: an in-place change may be visible through every reference to that collection.

Takeaway: Choose operations deliberately: read values when calculating, use indexes when assigning, and decide whether the result should mutate the original collection or be stored separately.

Traversing and Accumulating

means visiting collection elements systematically. A value-based is appropriate when the algorithm needs each value but not its position. An -based is appropriate when the algorithm needs positions, must update elements, or must compare neighboring elements.

A typical range for a collection of length nn begins at 00 and ends at n−1n-1. Stopping at nn would attempt one access beyond the final element.

Building results during

An begins with an initial value and is updated as elements are processed. To total the values 44, 88, and 1515, initialize the total to 00, then add each element:

  • After processing 44, the total is 44.

  • After processing 88, the total is 1212.

  • After processing 1515, the total is 2727.

The same pattern can count elements satisfying a condition, calculate an average, or build a result collection. A count of passing scores, for instance, starts at 00 and increases by 11 whenever a score is at least 6060.

Takeaway: A supplies the repeated processing step, while an preserves the result built so far.

Selecting, Transforming, and Updating

Many collection algorithms can be understood as one of three related patterns.

Selecting elements

keeps only elements that satisfy a condition. To create a collection of passing scores, examine each score and append it to the result when the score is at least 6060. The original scores remain available if the passing results are stored separately.

Producing corresponding values

creates one output value for each input value. If the input values are 22, 55, and 77, multiplying each by 22 produces 44, 1010, and 1414. A new collection is useful when the original values must be preserved.

Finding an extreme value

To find the largest value in a nonempty collection, initialize the candidate maximum with the first element. Compare the remaining elements with that candidate and replace it when a larger value is found. Initializing the maximum to 00 is unsafe if all valid inputs might be negative.

Updating in place

An -based can replace each element directly. For example, multiplying every element by 22 changes the original collection rather than creating a separate doubled collection.

Takeaway: Selecting keeps some elements, transforming creates corresponding results, and in-place updating changes existing elements. The intended result determines which pattern to use.

Searching and Combining Operations

A examines elements in order until it finds a target or reaches the end. A useful search procedure returns the matching when the target is found and returns −1-1 when it is absent.

For the collection [12,7,19,4][12, 7, 19, 4], searching for 1919 returns 22. Searching for 1010 returns −1-1. The nonnegative result communicates success, while −1-1 communicates failure.

A has worst-case running time O(n)\mathrm{O}(n), where nn is the collection's length, because it may inspect every element. A sorted collection may support a binary search with fewer comparisons, but binary search is a different strategy and depends on maintaining sorted data.

Search and update can be combined. For example, an algorithm can traverse a collection and replace every negative value with 00. Because the algorithm assigns values back into the original positions, it needs indexes rather than only copied element values.

Takeaway: A search needs a clear result convention, and an update needs a way to identify the position being changed.

Nested Data and Reliable Boundaries

A collection can contain other collections. This creates a row-and-column structure suitable for tables, grids, game boards, and spreadsheets. For example, a two-row table can contain the rows [80,90,85][80, 90, 85] and [75,88,92][75, 88, 92].

The first selects a row, and the second selects a column. In this example, row 00 and column 11 identify the value 9090. Processing every cell requires a loop for the rows and an inner loop for the elements of each row.

If a rectangular table has rr rows and cc columns, visiting every cell requires approximately r×cr \times c element visits. Each loop must respect the valid bounds of the collection it traverses.

Boundary and correctness checks

Test collection algorithms with:

  • An empty collection.

  • A one-element collection.

  • A target at the first position.

  • A target at the last position.

  • A target that does not occur.

  • Duplicate values.

  • Negative values when they are allowed.

  • An attempted equal to the collection length.

Frequent errors include starting at 11 and skipping the first element, accessing nn instead of stopping at n−1n-1, initializing an extreme-value search with an unsuitable constant, changing collection length during , and unintentionally mutating shared data.

Takeaway: Boundary cases reveal off-by-one errors and unsafe assumptions that ordinary examples may hide.