How to handle that a start and end in the wrong order?

Presumably the function crashes (can’t see it all) and presumably the error message is testing for one thing, but reports something else. So both your code and codecademy’s code each has a bug.

specifically the test contains this code:

except TypeError:
  fail_tests("Your function should accept a parameter `word` and parameters `start` and `end`")

which is suggesting that a TypeError means that there are missing parameters … no it doesn’t, and function parameters can be inspected so there is no reason to do something this crude.

2 Likes

When starting this exercise i though but if there’s something like this:

substring_between_letters(“applee”, “p”, “e”)

It might end up printing “pl” instead of “ple” if i will use word.find(end) because it will return the first index of “end” in “word”
So I ended up doing like this:

def substring_between_letters(word, start, end):
  if start in word:
    start_index = word.find(start)
    if end in word:
      for i in range(len(word)):
        if end == word[i]:
          end_index = i
      new_word = word[start_index+1:end_index]
      return new_word
    else:
      return word
  else:
    return word

this part loops through letters in “word” and saves the last index of a letter that is equal to the letter of “end”.

      for i in range(len(word)):
        if end == word[i]:
          end_index = i

hope this will be useful as a different approach for others.

1 Like

This should handle:

  1. Start and End in a wrong order

  2. Start and End are the same letters

What about searching for start in word, then cutting out the word for what is left after the start, only then searching for ending in what is left

def substring_between_letters(word, start, end):
  startIndex = word.find(start)
  if startIndex == -1:
    return word
  endIndex = word[startIndex + 1:].find(end)
  if endIndex == -1:
    return word
  return word[startIndex + 1: startIndex + 1 + endIndex] 

when I try something like example one, it always returns nothing instead of the full word. Why is that so? I am a bit confused now. Help would be greatly appreciated! .)

Please share what code you are running for us to see. Thanks.

So, if I use this code:

def random_funtion(string, start, end):
index_start = string.find(start)
index_end = string.find(end)
if index_start or index_end == -1:
return string
return string[index_start + 1:index_end]

print(random_funtion(“adogbhjam”, “b”, “a”))

–> it returns the original string but I don’t get why because neither of the indexes is == -1 .
index_start is 4 and index_end is 0.
–> if I delete the if condition, then it just returns nothing

We need to make the same comparison in the first operand as second one.

got it. thank you :grinning:

2 Likes

Hi fellow coders! I passed the challenge with this code (didn’t peek) =>

def substring_between_letters(word, start, end):
  start = word.find(start) 
  end = word.find(end) 
  if not start == -1 and not end == -1:
    return word[1 + start:end]
  else:
    return word 

Can someone tell me if this code is legit?
I find puzzling this part word[1 + start:end]; not so sure what I did there.

Came up with this, which will return word, unless it can find start, and find end, and the index of start is smaller than the index of n.

def substring_between_letters(word, start, end):
if start in word and end in word and word.find(start)<word.find(end):
arg1 = word.find(start)
arg2 = word.find(end)
return word[arg1+1:arg2]
else:
return word

I guess if the index of end is smaller that the index of start and you still want the substring between the two first instances of the letters, you could have this:

def substring_between_letters(word, start, end):
if start in word and end in word and word.find(start)<word.find(end):
arg1 = word.find(start)
arg2 = word.find(end)
return word[arg1+1:arg2]
if start in word and end in word and word.find(start)>word.find(end):
arg1 = word.find(end)
arg2 = word.find(start)
return word[arg1+1:arg2]
else:
return word

word[1 + start:end]

In your approach you first get the index at which you found the character that is the same as in your variable start.

Later on you want to return the value(characters) between your start and end variable, so basically the next index you found for start and the previous index you found end. To achive this and the way slicing works you need to add +1 to the index in start. No need to do this for end because it will be sliced to the previous index on its own. Look into slicing for a more professional explanation :slight_smile:

For the excersize you code seems legit to me, only did i think you if selection is hard to read. In my approach i included one more fault-check e.g. invalid order of input or same letter input.

def substring_between_letters(word, start, end):
  entry = word.find(start) + 1
  exit = word.find(end) 
  if entry == -1 or exit == -1:
    return "At least one letter not included"
  if entry >= exit:
    return "Invalid Input"
  return word[entry:exit]

Here’s my attempt:

def substring_between_letters(word, start, end):
  s_index = word.find(start)
  e_index = word.find(end)
  if s_index < 0 or e_index < 0 or s_index > e_index:
    return word
  return word[s_index+1:e_index]

This was my approach to this problem:

def substring_between_letters(word, start, end):
  # simplify the notation to mark the location of `start` and `end` in `word`
  s = word.find(start) # a value of `-1` means letter is not in string
  e = word.find(end) # a value of `-1` means letter is not in string
  # make sure both `start` and `end` are in `word`
  if (s != -1) and (e != -1):
    # return all letters between `start` and `end` (print nothing if `s==e`; return the substring in order even if `s > e`)
    if s < e:
      return word[s+1 : e]
    elif s > e:
      return word[e+1 : s]
    else:
      return ''
  # if either `start` or `end` are not in string, return `word`
  return word

Here are the tests I used to check my code (I added some that the lesson did not include):

# Test 1
print(substring_between_letters("apple", "p", "e"))

# Test 2
# should print "pl"

# Test 3
print(substring_between_letters("apple", "p", "c"))
# should print "apple"

# Test 4
print(substring_between_letters("apple", "q", "l"))
# should print "apple"

# Test 5
print(substring_between_letters("apple", "e", "p"))
# should print "pl"

# Test 6
print(substring_between_letters("apple", "l", "l"))
# should print ""
1 Like

Hi! Can someone help me understand what’s the +1 in start? thanks!

Hello @nahuelim,

return word[s+1 : end]

The +1 in the start positions you to the next character in the word string.

Here is a good explanation on string slicing: Python String Slicing - Learn By Example

I hope that helps.

My solution:
def substring_between_letters(word,start,end):

if start in word and end in word and word.find(start)!=word.find(end):

return word[word.find(start)+1:word.find(end)]

else: return word

My code appears to work except in cases where both start and end are the same character. How can I account for that in my code? I can’t seem to figure it out, even after looking at the replies in this thread so far. I’m quite new to coding so that doesn’t help.

Here is my code:

def substring_between_letters(word, start, end):
  word_start = word.find(start) + 1
  word_end = word.find(end)
  if word_end and word_start == -1:
    return word
  elif word_end < word_start:
    return word
  else:
    return word[word_start:word_end]

# Uncomment these function calls to test your function:
print(substring_between_letters("apple", "p", "e"))
# should print "pl" (this works)
print(substring_between_letters("apple", "p", "c"))
# should print "apple" (this also works)
print(substring_between_letters("mountain", "n", "n"))
#THE PROBLEM: should print "tai" but prints "mountain

Like a lot of similar methods .find only locates the first appearance of a matching substring- https://docs.python.org/3/library/stdtypes.html#str.find. If you check the docs you’ll see how to limit the range that .find searches through. Perhaps you could adapt your code to start the second search at an advanced position?

It’s worth noting that could change the behaviour for the regular match so consider whether you want to change the start only if the characters are the same or not. That’s probably up to you as you’re going beyond the instructions at this point :slightly_smiling_face:.

My solution:

def substring_between_letters(word, start, end):
  find_first = word.find(start)
  find_last = word.find(end)
  if (start != end) and ((start in word) and (end in word)):
    return word[find_first + 1:find_last]
  return word