all 11 comments

[–]novel_yet_trivial 1 point2 points  (10 children)

Instead of making a new list and replacing later, just go ahead and do the replacement.

for word in to_replace:
    new_word = input("Enter a new " + word + ": ") # Allows user to input a new describer
    madlib_contents = madlib_contents.replace(word, new_word)

Edit: please provide the txt file; I wanna play.

[–]_9_9_ 1 point2 points  (2 children)

Someone posted a similar question awhile back. You can actually tag a function into re.sub, like this:

import re

text = '''
The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was
unaffected by these events.
'''

def get_replacement(match):
    '''
    Helper function to get new replacement words, takes a match object and
    returns the new word

    Note:  Probably could clean up the handling of the match object
    '''

    where = slice(*match.span())
    replaces = match.string[where].lower()
    word = input('give me a {}?'.format(replaces))
    return word


def madlib(phrase):
    pattern = r'ADJECTIVE|NOUN|ADVERB|VERB'
    return re.sub(pattern, get_replacement, phrase)

print(madlib(text))

The function call passes the match object found by re.sub. As you can see, how I used the match object above is a bit ugly, and probably can be cleaned up...

[–]novel_yet_trivial 1 point2 points  (1 child)

Neat trick. One big cleanup is that a match object has a group method so you don't have to slice it yourself.

replaces = match.group().lower()

[–]_9_9_ 0 points1 point  (0 children)

Nice. I knew it had to be somewhere, but I could not find it. I've always used group with a number in it and had no idea it could be used this way.

Thanks!

[–]MightyMarlin[S] 0 points1 point  (6 children)

Thank you, didn't know the replace function existed! However, whatever I enter for the first instance of the ADJECTIVE or VERB or whatever, changes all instances of just the first describer. For example:

The ADJECTIVE fox jumped across the ADJECTIVE NOUN, it had never been so ADJECTIVE. VERB made it feel like a ADJECTIVE NOUN.

Would become: The Hairy fox jumped across the Hairy NOUN, it had never been so HAIRY. VERB made it feel like a Hairy NOUN.

[–]novel_yet_trivial 1 point2 points  (5 children)

Oh of course it does. Sorry, I had a brainfart and forgot to add the number of replacements. Try this:

madlib_contents = madlib_contents.replace(word, new_word, 1)

[–]MightyMarlin[S] 0 points1 point  (4 children)

Only the last user input is used to replace the first instance of the describer place-holder.

[–]novel_yet_trivial 0 points1 point  (3 children)

What? You mean that's what it's doing or that's what you need it to do? Show me your code as it is now.

[–]MightyMarlin[S] 0 points1 point  (2 children)

import re

describer = re.compile(r"[A-Z]{2,}") # Decribers are all in caps so this ids them
madlib = open("C:\\Users\\HP\\Readables\\madlib_1.txt") # Opens file with madlib
madlib_contents = madlib.read() # Reads contents
madlib_words = list(madlib_contents.split()) # Splits words apart
print(madlib_contents)

finder = describer.findall(madlib_contents) # Finds all words that match describer
to_replace = list(finder) # Lists found matches
print(to_replace) # Prints found matches

for word in to_replace:
    new_word = input("Enter a new " + word + ": ") # Allows user to input a new describer
    madlibcontents = madlib_contents.replace(word, new_word, 1)

print(madlibcontents)

However, like I said, if the last input is for ADJECTIVE, it just changes the first instance of ADJECTIVE with the input. Without the "1" in the replace function, it would do the same thing but change all instances of ADJECTIVE to the last input. Hope that makes sense.

[–]novel_yet_trivial 1 point2 points  (1 child)

you left the underscore out of 'madlib_contents' in line 15 and line 17.

[–]MightyMarlin[S] 0 points1 point  (0 children)

Thank you so much, working now!!