Today: more string algorithms, str in, if/elif, quick-return, str find, slices
Note: running tests, green run button near bottom
See Python guide: string, if
Problems today:
>
str2 functions
String in Test
- Built-ins xxx
- String has many built-in functions, we'll look at the most important
-
in - test if a substring appears in a string
- As usual, chars must match exactly - upper/lower are considered different
- True/False test - use .find() is need to know where char is
>>> 'c' in 'abcd'
True
>>> 'bc' in 'abcd'
True
>>> 'bx' in 'abcd'
False
>>> 'A' in 'abcd'
False
1. Catty function
`'xCtxxxAax' → 'CtAa'`
Return a string made of the chars from the original string, whenever the chars are 'c' 'a' or 't', (either lower or upper case). So the string 'xCaxxxTx' returns 'CaT'.
- Compute lowercase version of each char
- Create var "low" to hold intermediate result (strategy)
- Can write with "or"
- Can write with "in" - cute
Solution
def catty(s):
result = ''
for i in range(len(s)):
# Create "low" var of intermediate result
low = s[i].lower()
if low == 'c' or low == 'a' or low == 't':
result += s[i] # Use original, not low
return result
# Cute non-obvious alternative: use "in"
# to do the "or" logic for us, like this:
# if low in 'cat':
if/elif Structure
- Most common: regular if
- Second: if/else
Choose between 2 actions
- if/elif structure
- Evaluate test1, test2, test3
- As soon as test is true, run that action. We are done
- Optional "else:" at end runs if no test is true
if test1:
action-1
elif test2:
action-2
else:
action-3
2. str_adx()
- If/elif logic testing each char
- alpha, digit, otherwise
Solution
def str_adx(s):
result = ''
for i in range(len(s)):
if s[i].isalpha():
result += 'a'
elif s[i].isdigit():
result += 'd'
else:
result += 'x'
return result
Quick Return Strategy
- Discover answer: return with it right away
- Loop over everything looking for X
- Never find X
- Therefore there is no X
- return at bottom for no-x case
3. first_alpha()
Given a string s, return the first alphabetic char in s, or None if there is no alphabetic char. Demonstrates quick-return strategy.
Solution
def first_alpha(s):
for i in range(len(s)):
if s[i].isalpha():
return s[i]
# 1. Exit immediately if found
# 2. If we get here,
# there was no alpha char.
return None
4. has_digit()
Use quick-return strategy, returning True or False.
Given a string s, return True if there is a digit in the string somewhere, False otherwise.
for i in range(len(s)):
if s[i].isdigit():
# 1. Exit immediately if found
return True
# 2. If we get here,
# there was no digit.
return False
String find()
s.find(target_str)- search s for target_str
- Returns int index where found first
- Or -1 if not found
- str noun.verb function call style (aka "object oriented")
- Take optional 2nd "start_index" parameter, starts search from there
s.find(target_str, start_index)
>>> s = 'there'
>>> s.find('h')
1
>>> s.find('e')
2
>>> s.find('ere') # len > 1 ok
2
>>> s.find('x')
-1
>>> s.find('E')
-1
>>> s.find('e', 3) # start at 3
4
Python String Slices
- This is a great feature
- Dense! i.e. slow down when writing a slice
- "substring" - contiguous sub-part of a string
- Access substring with 2 numbers
- "slice" uses colon to indicate a range of indexes
s[1:3]
- Start at first number
- Up to but not including second number
- If start index is omitted, uses start of string
- If end index is omitted, uses end of string
- If number is too big .. uses end also
- Note perfect split: s[:4] and s[4:]
Number used as both start and end
Splits the str into 2 pieces
s[3:3] = empty string
"Not including" number dominates
- Try it in the interpreter
- Style: typically written with no spaces around ":"
>>> s = 'Python'
>>> s[1:3]
'yt'
>>> s[1:5]
'ytho'
>>> s[3:3] # "not including" dominates
''
>>>
>>> s[:3] # omit = from/to end
'Pyt'
>>> s[4:]
'on'
>>> s[4:999] # too big = to end
'on'
>>> s[:4] # "perfect split" on 4
'Pyth'
>>> s[4:]
'on'
>>> s[:] # the whole thing
'Python'
Brackets Problem
>
brackets
- Problems like: extracting email address from a text message
- Given
cat[dog]bird' → dog`
- Given: either 2 brackets, or zero brackets
- Strategy:
- Use .find()
left = s.find('[')
- Store value in variable
left for later lines
Partial results in well-named variable
An important technique
- Look for right bracket
- Use slice to pull out and return answer
Brackets Observations
- Make a diagram - work out the index numbers
- Code should work in general
- BUT can use specific string to work out numbers
- e.g. 'cat[dog]bird'
- Empty string input - works?
- What about input 'a[]z'
Verify that our slice works here too
Optional: Negative Slice
- You do not need to use these!
- Handy shortcut, a little advanced
- Negative numbers to refer to chars at end of string
- -1 is the last char
- -2 is the next to last char
- Works in slices etc.
>>> s = 'Python'
>>> s[len(s)-1]
'n'
>>> s[-1]
'n'
>>> s[-2]
'o'
>>> s[1:-3]
'yt'
>>> s[-3:]
'hon'