Menu

Programming Fundamentals

String Manipulation

Contents

  1. Strings
  2. String length and indexing
  3. String slicing
  4. Changing case
  5. Character codes: ord() and chr()
  6. Loops and strings

A string is a sequence of characters — anything you can type: letters, digits, spaces and symbols such as commas, dashes or exclamation marks. Every piece of text a program holds is a string, even something that looks like a number such as "07700 900123", because the quote marks make it text rather than a value to do arithmetic with.

Strings turn up everywhere: a player name on a scoreboard, an answer typed at an input() prompt, a message printed to the screen. The characters are kept in order, so a string can be counted, copied in part or rebuilt.

What string manipulation means

String manipulation means working with the characters inside a string instead of treating the whole thing as one lump. A program rarely wants text exactly as it was typed — it may need to count the characters, pull out part of a code, glue two names together, ignore capital letters or turn a letter into its code.

TaskTool
Count the characterslen()
Pick out one character[i]
Copy out part of the string[start:end]
Join strings end to end+
Switch between capitals and lowercase.upper() and .lower()
Swap a character for its code, and backord() and chr()
Visit every character in turna loop

Tools you will not need

Python has many more string methods, such as split(), replace(), find() and count(). These are not required here and questions will not depend on them, because the same jobs — counting how often a letter appears in a word, checking whether a booking reference contains a certain letter, or building a display label from parts of a title — can be done with the tools in the table.

# a string can hold letters, digits, spaces and symbols
fixture = "Match 3: Kestrels vs Hawks!"
print(fixture)
print(len(fixture))
print(fixture.upper())

Output:

Match 3: Kestrels vs Hawks!
27
MATCH 3: KESTRELS VS HAWKS!

A string is a sequence of characters, and each character has a numbered position called an index. Counting starts at 0, not 1, so the first character of "BeachParty" is B at index 0 and the second is e at index 1.

You select one character by putting its index in square brackets after the string or the variable holding it. If word = "BeachParty", then word[0] gives B and word[4] gives h.

word = "BeachParty"
print(word[0])
print(word[4])
print(len(word))
print(len(word) - 1)

Output:

B
h
10
9

Length and the last index

The len() function returns how many characters a string contains, as an integer. len("BeachParty") is 10. Every character counts, including spaces and symbols: "Order #27!" has 10 characters because the space, the hash and the exclamation mark are characters too.

Because counting starts at 0, the index of the last character is always the length minus 1. For "BeachParty" that is 10 - 1 = 9, which holds the final y. Valid indexes run from 0 up to the length minus 1; using an index equal to or greater than the length, such as word[10], causes an error.

Checking a length

You can use len() to test whether a piece of text is a suitable length. This chat message is only allowed up to 20 characters, so the program compares the length with 20 and prints a warning if it is over the limit. The same comparison checks that a password or code is long enough before it is accepted.

message = input("Enter your message: ")
if len(message) > 20:
    print("Message too long")
else:
    print("Message sent")

Output when the user types See you at the park after school:

Enter your message: See you at the park after school
Message too long

A substring is a part of a string. Slicing extracts a substring using square brackets with a start position and an end position separated by a colon, such as [2:5].

The character at the start position is included, but the character at the end position is not. In the string kangaroo, position 2 is n and position 5 is r. The slice kangaroo[2:5] takes positions 2, 3 and 4, giving nga. Position 5 is only the stopping point, so no character from it is included.

How many characters a slice contains

The number of characters in a slice is the end position minus the start position: 5 − 2 = 3 characters. To take a known number of characters from a given start, add the number you need to the start to find the end. Starting at 4 and taking 3 characters uses [4:7], because 4 + 3 = 7.

Leaving positions out

  • Omit the start and slicing begins at position 0. So [:3] gives the first 3 characters.
  • Omit the end and the slice runs to the end of the string. So [4:] starts at position 4 and keeps every character after it.
  • For the last few characters whatever the length, start at the string length minus the number required and leave out the end. For the last 4 characters of a string stored in word, use word[len(word) - 4:].

A slice of length one can pick out the same single character as indexing. word[3:4] contains one character, just like word[3].

word = input("Enter a word: ")
print(word[1:4])
print(word[:2])
print(word[len(word) - 3:])

Output when the user types sprinkler:

Enter a word: sprinkler
pri
sp
ler

Building route codes

Slices are useful when a code or label must be made from parts of existing strings. Take each slice, change its case if needed, then join the pieces with +. For example, the first two letters of Norwich and the last four letters of Manchester can become no + ster, making the route code noster.

departure = input("Departure station: ")
arrival = input("Arrival station: ")
departure_part = departure[:2].lower()
arrival_part = arrival[len(arrival) - 4:].lower()
route_code = departure_part + arrival_part
print(route_code)

Output when the user types Norwich, Manchester:

Departure station: Norwich
Arrival station: Manchester
noster

upper() and lower() are string methods that make a changed copy of a string. upper() turns every letter into a capital letter, and lower() turns every letter into a small letter.

You must put the brackets after the method name, because the brackets are what tell Python to carry out the method now. Writing sport.upper with no brackets does not convert anything.

Only letters change

Digits, spaces and punctuation are not letters, so they are left exactly as they are. A phrase keeps its spaces and its numbers in the same places, whichever method you use.

ExpressionResult
sport (where sport is "Match 3 Goals")Match 3 Goals
sport.upper()MATCH 3 GOALS
sport.lower()match 3 goals

A new string is returned

Both methods return a new string. The string stored in the variable is not edited in place, so if you want to keep the converted version you must store it, for example code = badge.upper() leaves the original text in badge and puts the capitalised version into code.

sport = "Match 3 Goals"
print(sport.upper())
print(sport.lower())
print(sport)

Output:

MATCH 3 GOALS
match 3 goals
Match 3 Goals

Comparing without worrying about case

Two strings only match if every character matches, and a capital letter is a different character from the same small letter. To make a case-insensitive comparison, convert the input and the stored answer to the same case with lower() before using ==. A user can then type an answer in capitals, small letters or a mixture and still be marked correct.

planet = "Jupiter"
guess = input("Name the largest planet: ")
if guess.lower() == planet.lower():
    print("Correct")
else:
    print("Not quite")

Output when the user types JuPiTeR:

Name the largest planet: JuPiTeR
Correct

A character code is the number a computer stores to stand for a character, such as its ASCII code. Python gives you two built-in functions for swapping between a character and its code, and they work in opposite directions.

ord() and chr()

ord() takes a single character and returns its numeric code. chr() takes a code and returns the matching one-character string. Passing more than one character to ord() causes an error, and chr() needs a code that exists in the character set.

FunctionWhat it doesType of result
ord()finds the code for one characterinteger
chr()finds the character for a codestring

For example, the capital letter T has code 84, so chr() with 84 gives back T.

Moving along the alphabet

Within each case, letter codes go up in alphabetical order, so adding to a code moves you forward through the alphabet until Z. If the code for K is 75, then adding 4 gives 79, which is the code for O, four letters later. The first step finds the starting code with ord(), the arithmetic works out a new code, and chr() turns that code back into a character.

Changing case with codes

An uppercase letter always has a lower code than the same letter in lowercase, and the gap between the two cases is identical for all 26 letters. Subtracting the code for an uppercase letter from the code for the same lowercase letter always gives that same gap, so subtracting it from a lowercase code gives the uppercase letter and adding it to an uppercase code gives the lowercase letter. For example, adding the gap to the code for W gives the code for w.

start_char = input("Type a capital letter: ")
case_gap = ord('w') - ord('W')   # distance from uppercase to lowercase
print("Four along:", chr(ord(start_char) + 4))
print("Lowercase:", chr(ord(start_char) + case_gap))

Output when the user types K:

Type a capital letter: K
Four along: O
Lowercase: k

A string is a sequence of characters, and each character sits at a numbered position called an index, starting at 0. A count-controlled loop can use those indexes as its counter, so the loop body works on one character at a time.

Visiting every character

A loop written as for i in range(0, len(s)): gives i the values 0, 1, 2 and so on up to len(s) - 1, which is every valid index. Inside the loop s[i] picks out the character at that index, so each character is visited exactly once. The end value of range() is not included, which is why writing len(s) is safe: the loop stops before the position that would be past the end of the string.

Counting characters that meet a condition

Set a total to 0 before the loop, then use an if inside the loop to test each character. When the test is true, add 1 to the total. For example, a row of seats marked "OOXXOXO" uses X for booked, so testing each character against "X" and adding 1 when it matches counts the booked seats. If capital and lowercase letters should count the same, store s = s.lower() first, so every character is compared in a consistent case.

seats = "OOXXOXO"
booked = 0
for i in range(0, len(seats)):
    if seats[i] == "X":
        booked = booked + 1
print("Booked seats:", booked)

Output:

Booked seats: 3

Building a new string

Start with an empty string, then join one character at a time by writing newText + s[i] and storing the answer back in newText. Each pass makes the new string one character longer. Choosing which characters to add lets you build a filtered string, such as keeping only the digits from a code.

To visit the characters in reverse, give range() a step of -1: range(len(s) - 1, -1, -1) counts down from the last index to 0. Adding each character to the end of the new string as you go puts them in that order, so the finished string is the original written backwards.

chosen = input("Enter a word: ")
secret = ""
for i in range(len(chosen) - 1, -1, -1):
    secret = secret + chosen[i]
print(secret)

Output when the user types garden:

Enter a word: garden
nedrag

Also useful