0

I am a beginner in Python, I am teaching myself off of Google Code University online. One of the exercises in string manipulation is as follows:

# E. not_bad
# Given a string, find the first appearance of the
# substring 'not' and 'bad'. If the 'bad' follows
# the 'not', replace the whole 'not'...'bad' substring
# with 'good'.
# Return the resulting string.
# So 'This dinner is not that bad!' yields:
# This dinner is good!
def not_bad(s):
  # +++your code here+++
  return

I'm stuck. I know it could be put into a list using ls = s.split(' ') and then sorted with various elements removed, but I think that is probably just creating extra work for myself. The lesson hasn't covered RegEx yet so the solution doesn't involve re. Help?

Here's what I tried, but it doesn't quite give the output correctly in all cases:

def not_bad(s):
  if s.find('not') != -1:
    notindex = s.find('not')
    if s.find('bad') != -1:
      badindex = s.find('bad') + 3
      if notindex > badindex:
        removetext = s[notindex:badindex]
        ns = s.replace(removetext, 'good')
      else:
        ns = s
    else:
      ns = s
  else:
    ns = s
  return ns

Here is the output, it worked in 1/4 of the test cases:

not_bad
  X  got: 'This movie is not so bad' expected: 'This movie is good'
  X  got: 'This dinner is not that bad!' expected: 'This dinner is good!'
 OK  got: 'This tea is not hot' expected: 'This tea is not hot'
  X  got: "goodIgoodtgood'goodsgood goodbgoodagooddgood goodygoodegoodtgood  
     goodngoodogoodtgood" expected: "It's bad yet not"

Test Cases:

print 'not_bad'
  test(not_bad('This movie is not so bad'), 'This movie is good')
  test(not_bad('This dinner is not that bad!'), 'This dinner is good!')
  test(not_bad('This tea is not hot'), 'This tea is not hot')
  test(not_bad("It's bad yet not"), "It's bad yet not")

UPDATE: This code solved the problem:

def not_bad(s):
  notindex = s.find('not')
  if notindex != -1:
    if s.find('bad') != -1:
      badindex = s.find('bad') + 3
      if notindex < badindex:
        removetext = s[notindex:badindex]
        return s.replace(removetext, 'good')
  return s

Thanks everyone for helping me discover the solution (and not just giving me the answer)! I appreciate it!

1
  • "The lesson hasn't covered RegEx yet so the solution doesn't involve re." But it'd be soooo easyyyy... s = re.sub('not.*?bad', 'good', s). docs.python.org/library/re.html Commented Aug 4, 2011 at 18:19

5 Answers 5

3

Well, I think that it is time to make a small review ;-)

There is an error in your code: notindex > badindex should be changed into notindex < badindex. The changed code seems to work fine.

Also I have some remarks about your code:

  1. It is usual practice to compute the value once, assign it to the variable and use that variable in the code below. And this rule seems to be acceptable for this particular case:

For example, the head of your function could be replaced by

notindex = s.find('not')
if notindex == -1:
  1. You can use return inside of your function several times.

As a result tail of your code could be significantly reduced:

if (*all right*):
    return s.replace(removetext, 'good')
return s

Finally i want to indicate that you can solve this problem using split. But it does not seem to be better solution.

def not_bad( s ):
    q = s.split( "bad" )
    w = q[0].split( "not" )
    if len(q) > 1 < len(w):
        return w[0] + "good" + "bad".join(q[1:])
    return s
Sign up to request clarification or add additional context in comments.

Comments

3

Break it down like this:

  1. How would you figure out if the word "not" is in a string?
  2. How would you figure out where the word "not" is in a string, if it is?
  3. How would you combine #1 and #2 in a single operation?
  4. Same as #1-3 except for the word "bad"?
  5. Given that you know the words "not" and "bad" are both in a string, how would you determine whether the word "bad" came after the word "not"?
  6. Given that you know "bad" comes after "not", how would you get every part of the string that comes before the word "not"?
  7. And how would you get every part of the string that comes after the word "bad"?
  8. How would you combine the answers to #6 and #7 to replace everything from the start of the word "not" and the end of the word "bad" with "good"?

1 Comment

good stuff here. digitaltoday, I expect they want you to learn about slicing, which is kinda special to Python. I hope that's not too much of a clue.
1

Since you are trying to learn, I don't want to hand you the answer, but I would start by looking in the python documentation for some of the string functions including replace and index.

Also, if you have a good IDE it can help by showing you what methods are attached to an object and even automatically displaying the help string for those methods. I tend to use Eclipse for large projects and the lighter weight Spyder for small projects

2 Comments

Spyder looks nice, but the fact that there don't seem to be any Python 3 builds on the Google Code site disappoints me. For now I'll probably stick with lightweight IDEs that wouldn't require me to modify all the source myself to get everything working with Python 3. Oh well.
Yes, Spyder is currently geared mostly for people using PythonXY which is still using the 2.x series of python since some of the important libraries have not been ported to 3.x just yet.
1

http://docs.python.org/library/stdtypes.html#string-methods

I suspect that they're wanting you to use string.find to locate the various substrings:

>>> mystr = "abcd"
>>> mystr.find("bc")
1
>>> mystr.find("bce")
-1

Since you're trying to teach yourself (kudos, BTW :) I won't post a complete solution, but also note that you can use indexing to get substrings:

>>> mystr[0:mystr.find("bc")]
'a'

Hope that's enough to get you started! If not, just comment here and I can post more. :)

Comments

0
def not_bad(s):
    snot = s.find("not")
    sbad = s.find("bad")
    if snot < sbad:
        s = s.replace(s[snot:(sbad+3)], "good")
        return s
    else:
        return s

1 Comment

While this code may resolve the OP's issue, it is best to include an explanation as to how your code addresses the OP's issue. In this way, future visitors can learn from your post, and apply it to their own code. SO is not a coding service, but a resource for knowledge. Also, high quality, complete answers are more likely to be upvoted. These features, along with the requirement that all posts are self-contained, are some of the strengths of SO as a platform, that differentiates it from forums. You can edit to add additional info &/or to supplement your explanations with source documentation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.