4

Im trying to come up with something that will "title" a string of words. It should capitalize all words in the string unless given words not to capitalize as an argument. But will still capitalize the first word no matter what. I know how to capitalize every word, but I dont know how to not capitalize the exceptions. Kind of lost on where to start, couldnt find much on google.

  def titlemaker(title, exceptions):
      return ' '.join(x[0].upper() + x[1:] for x in title.split(' '))

or

return title.title()

but I found that will capitalize a letter after an apostrophe so I dont think I should use it. Any help on how I should take into account the exceptions would be nice

example: titlemaker('a man and his dog', 'a and') should return 'A Man and His Dog'

CDog
  • 111
  • 1
  • 1
  • 6
  • 3
    Possible duplicate, see http://stackoverflow.com/questions/3728655/python-titlecase-a-string-with-exceptions – Alex Jan 13 '16 at 23:28
  • Sort of a duplicate, I saw that post, but it doesnt show anything about a function with two arguments. He also used a set list all the time, I would like to be able to write which ones I dont want to capitalize. – CDog Jan 13 '16 at 23:34
  • `def title_except(s, exceptions)` seems to have two input arguments:-) – Alex Jan 13 '16 at 23:37

4 Answers4

4
def titlemaker(title,exceptions):
    exceptions = exceptions.split(' ')
    return ' '.join(x.title() if nm==0 or not x in exceptions else x for nm,x in enumerate(title.split(' ')))

titlemaker('a man and his dog','a and') # returns "A Man and His Dog"

The above assumes that the input string and the list of exceptions are in the same case (as they are in your example), but would fail on something like `titlemaker('a man And his dog','a and'). If they could be in mixed case do,

def titlemaker(title,exceptions):
    exceptionsl = [x.lower() for x in exceptions.split(' ')]
    return ' '.join(x.title() if nm==0 or not x.lower() in exceptions else x.lower() for nm,x in enumerate(title.split(' ')))

titlemaker('a man and his dog','a and') # returns "A Man and His Dog"
titlemaker('a man AND his dog','a and') # returns "A Man and His Dog"
titlemaker('A Man And His DOG','a and') # returns "A Man and His Dog"
Matthew
  • 7,440
  • 1
  • 24
  • 49
2

Try with this:

def titleize(text, exceptions):
    exceptions = exceptions.split()
    text = text.split()
    # Capitalize every word that is not on "exceptions" list
    for i, word in enumerate(text):
        text[i] = word.title() if word not in exceptions or i == 0 else word
    # Capitalize first word no matter what
    return ' '.join(text)

print titleize('a man and his dog', 'a and')

Output:

A Man and His Dog
Andrés Pérez-Albela H.
  • 4,003
  • 1
  • 18
  • 29
2
def titleize(text, exceptions):
    return ' '.join([word if word in exceptions else word.title()
                     for word in text.split()]).capitalize()
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
  • Doesn't the .title() at the end undo the exceptions? It looks like it splits the text into words, joins the words with non-exceptions title-cased, and then applies .title() to the resulting string which will title-case all words, including the exceptions. – Garland Pope Jan 04 '21 at 18:52
  • @GarlandPope I believe you're right. I've fixed it to finally call [`capitalize`](https://docs.python.org/3/library/stdtypes.html#str.capitalize) instead of [`title`](https://docs.python.org/3/library/stdtypes.html#str.title) so that the first character is always a capital. – Peter Wood Jan 04 '21 at 20:32
2
import re 
import nltk
from nltk.corpus import stopwords
from itertools import chain

def setTitleCase(title):
    exceptions = []
    exceptions.append([word for word in stopwords.words('english')])
    exceptions.append([word for word in stopwords.words('portuguese')])
    exceptions.append([word for word in stopwords.words('spanish')])
    exceptions.append([word for word in stopwords.words('french')])
    exceptions.append([word for word in stopwords.words('german')])
    exceptions = list(chain.from_iterable(exceptions))
    list_of_words = re.split(' ', title) 
    final = [list_of_words[0].capitalize()] 
    for word in list_of_words[1:]: 
        word = word.lower()
        if word in exceptions:
            final.append(word)
        else:
            final.append(word.capitalize())
    return " ".join(final)

print(setTitleCase("a Fancy Title WITH many stop Words and other stuff"))

Wich gives you as answer: "A Fancy Title with Many Stop Words and other Stuff"