loops + strings (slides)

CSc 110 - looping through strings

String Manipulation

String indexing

  • Strings are sequences in Python
  • We can retrieve values in a sequence using [ ]
name = "Xinchen"
name[0]
'X'

Note that the first index in a sequence is always zero.

String indexing

Since the first index of a sequence is zero, the last index is going to be the length of the string minus 1

name = "Xinchen"
len(name)
7
name = "Xinchen"
name[6]
'n'
name = "Xinchen"
name[7] # this will throw an error

Write a function

Function four_letter_anagram takes a string, and four integers a, b, c and d. It returns the anagram of the string according to the indices a, b, c and d – concatenate the individual characters.

Test cases:

assert four_letter_anagram("balm", 2, 1, 3, 0) == 'lamb'
assert four_letter_anagram("loin", 0, 2, 1, 3) == 'lion'
assert four_letter_anagram("reap", 3, 1, 2, 0) == 'pear'

Write a function - solution

def four_letter_anagram(word, a, b, c, d):
  return word[a] + word[b] + word[c] + word[d]

def main():
  assert four_letter_anagram("balm", 2, 1, 3, 0) == 'lamb'
  assert four_letter_anagram("loin", 0, 2, 1, 3) == 'lion'
  assert four_letter_anagram("reap", 3, 1, 2, 0) == 'pear'

main()

in operator

The in operator determines whether a given value is a constituent element of a sequence (such as a string)

"i" in "aeiou"
True
"eio" in "aeiou"
True
not "b" in "aeiou"
True
"0" in  "0987654321."
True
"10.0" in  "0987654321."
False

Question

How to check if a string can be converted to an integer or float?

  • "BladeRunner2049" will return False

  • "2049" will return True

  • "12.5" will return True

Question

How to check if a string can be converted to an integer or float?

Can we use the string method.isnumeric()?

user_input = "BladeRunner2049"
user_input.isnumeric()
False
user_input = "2049"
user_input.isnumeric()
True
user_input = "12.5"
user_input.isnumeric()
False

Iterating a string

  • One technique that can be used to control the number of loop iterations is using an index variable
  • For while loops, an index variable is:
    • Defined before the loop
    • Used in the condition of the loop
    • Incremented within the loop

Iterating a string

Print characters at even indices.

word = "BladeRunner2049"
index = 0
while index < len(word):
    print(word[index])
    # Can add other lines here too
    index = index + 2
B
a
e
u
n
r
0
9

Write a function

Function name is_numeric that takes one string argument of any length (assume length > 0).

It returns True if every character in the argument is a digit (0-9) or a period (.), False otherwise.

Use in operator instead of built-in function isnumeric().

assert is_numeric("BladeRunner2049") == False
assert is_numeric("2049") == True
assert is_numeric("12.5") == True

is_numeric() solution

How do we change our function so that the last test case (“1.2.3”) returns False instead?

def is_numeric(my_string):
  index = 0
  while index < len(my_string):
    if my_string[index] not in "0123456789.":
      return False
    index += 1
  return True

def main():
  assert is_numeric("BladeRunner2049") == False
  assert is_numeric("2049") == True
  assert is_numeric("12.5") == True
  assert is_numeric("1.2.3") == True # how to return False?
  
main()

is_numeric() – solution 1

def is_numeric(my_string):
  index = 0
  count_period = 0
  while index < len(my_string):
    if my_string[index] == ".":
      count_period += 1
    if my_string[index] not in "0123456789." or count_period > 1:
      return False
    index += 1
  return True

def main():
  assert is_numeric("234") == True
  assert is_numeric("abc") == False
  assert is_numeric("12c") ==  False
  assert is_numeric("12.3") == True
  assert is_numeric("1.2.3") == False
  
main()

is_numeric() – solution 2

def is_numeric(my_string):
  # create control variable for one decimal point
  decimal_point = False
  # create index variable
  index = 0
  while index < len(my_string):
    # first check, can character be found in a number?
    if my_string[index] not in "0123456789.":
      return False
    # second check, if a period, has a period been found before?
    if my_string[index] == ".":
      if decimal_point: # a previous period was detected
        return False
      else: # first period detected
        decimal_point = True
    # increment index  
    index += 1
  # while loop executed without returning False
  # that means every character is valid, so return True
  return True

def main():
  assert is_numeric("234") == True
  assert is_numeric("abc") == False
  assert is_numeric("12c") ==  False
  assert is_numeric("12.3") == True
  assert is_numeric("1.2.3") == False
  
main()