Concepts / Working with Multiple Strings

Working with Multiple Strings

The find() method locates the position of a substring and returns its starting index; use find(substring, start_pos) to search from a specific position onward.

  • Programming
Interactive lab

Try it: Indexing and Slicing

How Python indexes a sequence from 0 (or from the end with negative numbers) and how a slice start:stop:step picks positions — with the exact CPython rules for omitted and out-of-range bounds.

How it works

  1. Positions run 0 … len−1; negative positions count back from the end (−1 is the last).
  2. An index outside the string raises IndexError.
  3. A slice resolves start and stop (omitted → the ends; out of range → clamped), then walks by step, stopping before stop.
  4. A negative step walks backwards; a step of 0 is a ValueError.

Default run (7 steps): 'PYTHONIC'[1:6:2]: a slice copies characters from start up to (not including) stop, moving by step. … 'PYTHONIC'[1:6:2] → 'YHN' (positions 1, 3, 5).

Simplified: Works on a short string (up to 16 printable ASCII characters); lists slice by exactly the same rules.

Educational simulation

Loading the simulation…

From Mixed Text to Useful Data

Real-world data often arrives as one mixed string. A single line can contain an email address, a timestamp, and other information together. Parsing means breaking that string down so that you can isolate the exact substring you need. A practical parsing workflow combines find() to locate important landmarks with slicing to extract the characters between those landmarks.

Key point

The central idea is to let find() discover positions first, then use those positions as boundaries for a slice.

Reading Positions with find()

The find() method locates a substring within a string and returns the starting index of the first matching occurrence it finds. For example, in the source parsing example, find('@') returns 21. That result means the @ character is located at position 21 in the larger string. The returned number is useful because it can be stored conceptually as a landmark and then used in a later operation.

larger stringemail and surrounding text@position 2121starting indexcontainsfind('@') returns
Which character position does find() return, and how does that index identify a substring's location in the original string?

Searching from a Known Landmark

find() can receive a starting position as its second argument. The form find(substring, start_pos) begins searching from the specified position onward. In the source example, the position of @ is stored as 21. Searching for a space from that position returns 31, identifying the first space after the @ landmark.

larger stringcontains @ and spaces21search begins here31first space found afterwardfind('@')find(' ', 21)
How does providing a start position change where find() begins searching and which occurrence it returns?
Worked example

Two landmarks for one extraction

Use the source parsing sequence to identify the boundaries of a domain name.

  1. 1
    Find the first landmark

    find('@') returns 21, so the @ symbol is at position 21.

  2. 2
    Continue from that landmark

    find(' ', atpos) searches for a space beginning at position 21 and returns 31.

  3. 3
    Interpret the positions

    The @ at position 21 and the space at position 31 surround the domain portion that needs to be extracted.

Result

The two find() results provide the boundaries needed for the next slicing step.

Turning Landmarks into Slices

A slice written as [start:end] extracts characters beginning at start and continuing up to, but not including, end. In the source example, the slice data[atpos+1:sppos] begins one position after the @ and ends just before the space. Adding 1 to atpos skips the @ itself. Using sppos as the ending boundary excludes the space. The extracted result is the domain name uct.ac.za.

atpos21atpos + 122uct.ac.zacharacters betweenboundariessppos31skip @slice startslice end excluded
How does an index returned by find() become the start or end boundary of a slice?
Key point

The +1 is not arbitrary: it moves the slice start past the delimiter. The ending index remains the position of the space because the end of a slice is not included.

Tracing a Parsing Workflow

A complete parsing workflow can be traced as a sequence of dependent values. First, find() identifies the @ position. Next, that position becomes the starting point for a second find() search. Finally, both results flow into a slice. The first result is adjusted by 1 because the delimiter should not appear in the extracted text; the second result is used directly as the exclusive slice boundary.

source textmixed stringfind('@')21find(' ', 21)31data[22:31]start after @uct.ac.zaextracted domainlocate @start search at 21supply end 31supply start 21 + 1extract
What happens to each index as parsing moves from find() results into successive slice operations?
Worked example

Tracing the domain extraction

Follow the source example from the original string to the extracted domain.

  1. 1
    Record atpos

    The first search locates @ at position 21.

  2. 2
    Record sppos

    The second search starts at atpos and locates the next space at position 31.

  3. 3
    Build the boundaries

    The start boundary is atpos + 1, which is position 22. The end boundary is sppos, which is position 31.

  4. 4
    Apply the slice

    Characters from position 22 up to, but not including, position 31 form the desired substring.

Result

The extracted substring is uct.ac.za.

Checking Search Results

find() resultcandidate indexvalid indexnot -1slice datause boundariesintermediate valuesinspect parsingcheck resultyesno or unexpected
How should parsing logic be checked before a find() result is used in slicing?
  • Common mistake

    Using a find() result without checking whether it is valid

    What it looks like

    A parsing step continues directly from a search result to a slice.

    Why it fails

    The source guidance requires checking that find() returned a valid index rather than -1 before using it in a slice.

    Do this instead

    Verify the result first, and trace the intermediate values if the parsing result is unexpected.

  • Common mistake

    Starting the slice at the delimiter

    What it looks like

    The slice begins at the position of @ instead of one position after it.

    Why it fails

    The delimiter becomes part of the extracted substring.

    Do this instead

    Use the position after the delimiter when the delimiter itself should be skipped.

  • Common mistake

    Treating the slice end as included

    What it looks like

    The space position is expected to appear in the extracted result.

    Why it fails

    String slicing extracts up to but does not include the end boundary.

    Do this instead

    Use the delimiter's position as the end boundary when the delimiter should be excluded.

  • Common mistake

    Debugging only the final extracted text

    What it looks like

    An unexpected result is examined without checking the positions returned by find().

    Why it fails

    The error may come from either a landmark search or a slice boundary.

    Do this instead

    Inspect each find() result and then check how those indices flow into the slice.

Practice the Index Flow

MEDIUM

Explain the parsing sequence in your own words: first identify the position returned by find('@'), then identify the position returned by searching for a space from that position, and finally explain why the extraction starts one position after @ and ends at the space position.

Hints
  • Treat the two find() results as landmarks in the original string.
  • Remember that the slice end is excluded.
  • Ask which delimiter should be skipped at the beginning of the extracted substring.

What do you think happens?

The @ landmark is at position 21 and the following space is at position 31. What boundaries should be used to extract the domain without including either delimiter?

  • Start at 21 and end at 31

  • Start at 22 and end at 31

  • Start at 21 and end at 32

  • Start at 22 and end at 32

Reveal answer
Answer:

Start at 22 and end at 31.

Adding 1 to the @ position skips the @. Using 31 as the end boundary stops immediately before the space because slice end positions are not included.

Key Takeaways

  1. 1
    find() locates a substring and returns its starting index.
  2. 2
    find(substring, start_pos) begins the search from a specified position onward.
  3. 3
    A slice [start:end] includes the start boundary and stops before the end boundary.
  4. 4
    Parsing combines landmark searches with slicing to extract a precise substring.
  5. 5
    When parsing fails, verify that find() returned a valid index and trace every intermediate value into the slice.

At a glance

  • Use find() to turn important characters or substrings into usable position landmarks.
  • Give find() a starting position when the search should continue from a known point.
  • Combine find() results with slicing to extract the characters between delimiters.
  • Use one position after a starting delimiter and the delimiter's position as an exclusive ending boundary when appropriate.
  • Debug parsing by checking every search result and tracing how each index becomes a slice boundary.

Related concepts

More concepts starting with W