6
\$\begingroup\$

I've written a short script to use Reddit's PRAW API to search a subreddit for articles and if certain word/words are in the article title, replace those words with a random word taken from a list of other words. I'm putting it in a dictionary because I'm going to write the url & article title to a database before tweeting it out so I don't send out duplicates. I'm mostly curious if there's a better way to write the replacer() function.

For example: "World leaders brace for Trump's speech" --> "World leaders brace for spongebob's speech"

nicknames in matches() is a list of nicknames from another file.

def replacer(title, words, randoms):
    '''title is string you want to split.
       words is a list of words you are looking to match. 
       randoms is a list of random words to replace with words.'''

    new_title = []
    for word in title.split(' '):
        if word in words:
            word = random.choice(randoms)
        new_title.append(word)

    return ' '.join(new_title)


def matches(login, subreddit):

    page = login.subreddit(subreddit)

    # used for the any statement 
    combined_names = ["Name's", "Mister Name's", "Firstname Lastname", "Firstname", "Lastname", "Mister Firstname", "Mister Lastname"]

    # target words to replace 
    names_apost = ["Name's", "Mister Name's"] 
    names_no_apost = ["Firstname Lastname", "Firstname", "Lastname", "Mister Firstname", "Mister Lastname"]

    # for appropriate conjugation 
    nicknames_apostrophe = [i + "'s" for i in nicknames]

    post_dict = {}
    top_posts = page.hot(limit=100)
    for post in top_posts:
        title = post.title
    if any(word in title for word in combined_names):
        first_iter = replacer(post.title, names_apost, nicknames_apostrophe)
        second_iter = replacer(first_iter, names_no_apost, nicknames)
        if post.ups > 1000: 
            value = post.ups, post.url
            post_dict[second_iter] = value
    return post_dict
\$\endgroup\$
5
\$\begingroup\$

Note that the condition if word in words in replacer performs a linear search on words if it's a list, as in the current code. Since this condition is executed for every word in the input, it would be good to optimize it a bit. You could for example pass a set of words instead of a list.

The names first_iter and second_iter are not very meaningful. It would be good to come up with some better names for these.

\$\endgroup\$
3
\$\begingroup\$

Regarding your question about the replacer function, you can shorten it a bit by using list comprehensions:

def replacer(title, words, randoms):
    """
    :param title: string you want to split.
    :param words: list of words you are looking to match.
    :param randoms: list of random words to replace with words.
    :return: new title
    """

    return ' '.join([random.choice(randoms) if word in words else word 
                    for word in title.split()])

From the docs:

The method split() returns a list of all the words in the string, using str as the separator (splits on all whitespace if left unspecified), optionally limiting the number of splits to num

More, there's this PEP8 thing which tells Python programmers how they can style their code according to some simple rules:

  • for example, when writing docstrings you should use triple doubled-quotes
\$\endgroup\$
  • 1
    \$\begingroup\$ you don't even need the list expression. A generator expression would work just as well and not instantiate the list \$\endgroup\$ – Maarten Fabré Nov 10 '17 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.