s = 'the brown fox'
...do something here...
s
should be:
'The Brown Fox'
What's the easiest way to do this?
The .title()
method of a string (either ASCII or Unicode is fine) does this:
>>> "hello world".title()
'Hello World'
>>> u"hello world".title()
u'Hello World'
However, look out for strings with embedded apostrophes, as noted in the docs.
The algorithm uses a simple language-independent definition of a word as groups of consecutive letters. The definition works in many contexts but it means that apostrophes in contractions and possessives form word boundaries, which may not be the desired result: >>> "they're bill's friends from the UK".title() "They'Re Bill'S Friends From The Uk"
The .title()
method can't work well,
>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"
Try string.capwords()
method,
import string
string.capwords("they're bill's friends from the UK")
>>>"They're Bill's Friends From The Uk"
From the Python documentation on capwords:
Split the argument into words using str.split(), capitalize each word using str.capitalize(), and join the capitalized words using str.join(). If the optional second argument sep is absent or None, runs of whitespace characters are replaced by a single space and leading and trailing whitespace are removed, otherwise sep is used to split and join the words.
"There once was a string with an 'that had words right after it and then closed'"
. With this example all the worlds except for that
are capitalized as expected. The results being "There Once Was A String With An 'that Had Words Right After It And Then Closed'"
title()
for normal situations. In my situation, title()
returns a bad output for names with accents or dieresis, while capwords()
handled it correctly.
Just because this sort of thing is fun for me, here are two more solutions.
Split into words, initial-cap each word from the split groups, and rejoin. This will change the white space separating the words into a single white space, no matter what it was.
s = 'the brown fox'
lst = [word[0].upper() + word[1:] for word in s.split()]
s = " ".join(lst)
EDIT: I don't remember what I was thinking back when I wrote the above code, but there is no need to build an explicit list; we can use a generator expression to do it in lazy fashion. So here is a better solution:
s = 'the brown fox'
s = ' '.join(word[0].upper() + word[1:] for word in s.split())
Use a regular expression to match the beginning of the string, or white space separating words, plus a single non-whitespace character; use parentheses to mark "match groups". Write a function that takes a match object, and returns the white space match group unchanged and the non-whitespace character match group in upper case. Then use re.sub()
to replace the patterns. This one does not have the punctuation problems of the first solution, nor does it redo the white space like my first solution. This one produces the best result.
import re
s = 'the brown fox'
def repl_func(m):
"""process regular expression match groups for word upper-casing problem"""
return m.group(1) + m.group(2).upper()
s = re.sub("(^|\s)(\S)", repl_func, s)
>>> re.sub("(^|\s)(\S)", repl_func, s)
"They're Bill's Friends From The UK"
I'm glad I researched this answer. I had no idea that re.sub()
could take a function! You can do nontrivial processing inside re.sub()
to produce the final result!
string.capwords
does, according to the documentation in Chen Houwu's answer.
Here is a summary of different ways to do it, and some pitfalls to watch out for
They will work for all these inputs:
"" => ""
"a b c" => "A B C"
"foO baR" => "FoO BaR"
"foo bar" => "Foo Bar"
"foo's bar" => "Foo's Bar"
"foo's1bar" => "Foo's1bar"
"foo 1bar" => "Foo 1bar"
Splitting the sentence into words and capitalizing the first letter then join it back together: # Be careful with multiple spaces, and empty strings # for empty words w[0] would cause an index error, # but with w[:1] we get an empty string as desired def cap_sentence(s): return ' '.join(w[:1].upper() + w[1:] for w in s.split(' '))
Without splitting the string, checking blank spaces to find the start of a word def cap_sentence(s): return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) for i, c in enumerate(s) )
Or using generators: # Iterate through each of the characters in the string # and capitalize the first char and any char after a blank space from itertools import chain def cap_sentence(s): return ''.join( (c.upper() if prev == ' ' else c) for c, prev in zip(s, chain(' ', s)) )
Using regular expressions, from steveha's answer: # match the beginning of the string or a space, followed by a non-space import re def cap_sentence(s): return re.sub("(^|\s)(\S)", lambda m: m.group(1) + m.group(2).upper(), s)
Now, these are some other answers that were posted, and inputs for which they don't work as expected if we define a word as being the start of the sentence or anything after a blank space:
.title() return s.title() # Undesired outputs: "foO baR" => "Foo Bar" "foo's bar" => "Foo'S Bar" "foo's1bar" => "Foo'S1Bar" "foo 1bar" => "Foo 1Bar"
.capitalize() or .capwords() return ' '.join(w.capitalize() for w in s.split()) # or import string return string.capwords(s) # Undesired outputs: "foO baR" => "Foo Bar" "foo bar" => "Foo Bar" using ' ' for the split will fix the second output, but not the first return ' '.join(w.capitalize() for w in s.split(' ')) # or import string return string.capwords(s, ' ') # Undesired outputs: "foO baR" => "Foo Bar"
.upper() Be careful with multiple blank spaces, this gets fixed by using ' ' for the split (like shown at the top of the answer) return ' '.join(w[0].upper() + w[1:] for w in s.split()) # Undesired outputs: "foo bar" => "Foo Bar"
lower 123 upper
should return lower 123 Upper
, where the upper
is capitalized as it follows a number. I know it goes beyond the scope of the OP's question but a nice add-on to your already extensive answer. Thanks in advance.
"([0-9]+)(\s+.)"
instead of "(^|\s)(\S)"
(match one or more numbers, followed by one or more spaces, and any char after), or "([0-9]+)(\s*.)"
if you want to capitalize the character after 'zero or more' spaces after the number
WW1 - the great war
and output WW1 - The Great War
instead of Ww1 ...
. See the issue with abbreviations? Would you be willing to add something that demonstrates this case? I have been wondering about this for a while now and can't think of a way to do it.
WW1
would output as WW1
Copy-paste-ready version of @jibberia anwser:
def capitalize(line):
return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))
str.join
accepts generators.
join
accepts gen exps, In the case of str.join
particularly, it is generally preferred to use a list comprehension. This is because join
iterates twice over the argument, and hence it is faster to provide a ready-to-go list rather than a generator.
str.join
need to iterate twice over the argument? I just checked -- it doesn't. Though for small sequences list comprehension is faster indeed.
Why do you complicate your life with joins and for loops when the solution is simple and safe??
Just do this:
string = "the brown fox"
string[0].upper()+string[1:]
"the brown fox".capitalize()
?
'this is John'
into 'This is john'
.
string.capitalize()
(essentially echoing @luckydonald)
If str.title() doesn't work for you, do the capitalization yourself.
Split the string into a list of words Capitalize the first letter of each word Join the words into a single string
One-liner:
>>> ' '.join([s[0].upper() + s[1:] for s in "they're bill's friends from the UK".split(' ')])
"They're Bill's Friends From The UK"
Clear example:
input = "they're bill's friends from the UK"
words = input.split(' ')
capitalized_words = []
for word in words:
title_case_word = word[0].upper() + word[1:]
capitalized_words.append(title_case_word)
output = ' '.join(capitalized_words)
If only you want the first letter:
>>> 'hello world'.capitalize()
'Hello world'
But to capitalize each word:
>>> 'hello world'.title()
'Hello World'
'hello New York'.capitalize()
is 'Hello new york'
An empty string will raise an error if you access [1:]. Therefore I would use:
def my_uppercase(title):
if not title:
return ''
return title[0].upper() + title[1:]
to uppercase the first letter only.
str.capitalize
is for?
return title[:1].upper() + title[1:]
would also take care of that problem since slicing the empty string like that would give 2 empty strings, joined together make an empty string which is returned
Although all the answers are already satisfactory, I'll try to cover the two extra cases along with the all the previous case.
if the spaces are not uniform and you want to maintain the same
string = hello world i am here.
if all the string are not starting from alphabets
string = 1 w 2 r 3g
Here you can use this:
def solve(s):
a = s.split(' ')
for i in range(len(a)):
a[i]= a[i].capitalize()
return ' '.join(a)
This will give you:
output = Hello World I Am Here
output = 1 W 2 R 3g
As Mark pointed out, you should use .title()
:
"MyAwesomeString".title()
However, if would like to make the first letter uppercase inside a Django template, you could use this:
{{ "MyAwesomeString"|title }}
Or using a variable:
{{ myvar|title }}
The suggested method str.title() does not work in all cases. For example:
string = "a b 3c"
string.title()
> "A B 3C"
instead of "A B 3c"
.
I think, it is better to do something like this:
def capitalize_words(string):
words = string.split(" ") # just change the split(" ") method
return ' '.join([word.capitalize() for word in words])
capitalize_words(string)
>'A B 3c'
To capitalize words...
str = "this is string example.... wow!!!";
print "str.title() : ", str.title();
@Gary02127 comment, the below solution works with title with apostrophe
import re
def titlecase(s):
return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", lambda mo: mo.group(0)[0].upper() + mo.group(0)[1:].lower(), s)
text = "He's an engineer, isn't he? SnippetBucket.com "
print(titlecase(text))
You can try this. simple and neat.
def cap_each(string):
list_of_words = string.split(" ")
for word in list_of_words:
list_of_words[list_of_words.index(word)] = word.capitalize()
return " ".join(list_of_words)
Don't overlook the preservation of white space. If you want to process 'fred flinstone'
and you get 'Fred Flinstone'
instead of 'Fred Flinstone'
, you've corrupted your white space. Some of the above solutions will lose white space. Here's a solution that's good for Python 2 and 3 and preserves white space.
def propercase(s):
return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))
The .title() method won't work in all test cases, so using .capitalize(), .replace() and .split() together is the best choice to capitalize the first letter of each word.
eg: def caps(y):
k=y.split()
for i in k:
y=y.replace(i,i.capitalize())
return y
A quick function worked for Python 3
Python 3.6.9 (default, Nov 7 2019, 10:44:02)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> capitalizeFirtChar = lambda s: s[:1].upper() + s[1:]
>>> print(capitalizeFirtChar('помните своих Предковъ. Сражайся за Правду и Справедливость!'))
Помните своих Предковъ. Сражайся за Правду и Справедливость!
>>> print(capitalizeFirtChar('хай живе вільна Україна! Хай живе Любовь поміж нас.'))
Хай живе вільна Україна! Хай живе Любовь поміж нас.
>>> print(capitalizeFirtChar('faith and Labour make Dreams come true.'))
Faith and Labour make Dreams come true.
Capitalize string with non-uniform spaces
I would like to add to @Amit Gupta's point of non-uniform spaces:
From the original question, we would like to capitalize every word in the string s = 'the brown fox'
. What if the string was s = 'the brown fox'
with non-uniform spaces.
def solve(s):
# If you want to maintain the spaces in the string, s = 'the brown fox'
# Use s.split(' ') instead of s.split().
# s.split() returns ['the', 'brown', 'fox']
# while s.split(' ') returns ['the', 'brown', '', '', '', '', '', 'fox']
capitalized_word_list = [word.capitalize() for word in s.split(' ')]
return ' '.join(capitalized_word_list)
Easiest solution for your question, it worked in my case:
import string
def solve(s):
return string.capwords(s,' ')
s=input()
res=solve(s)
print(res)
Another oneline solution could be:
" ".join(map(lambda d: d.capitalize(), word.split(' ')))
space character
In case you want to downsize
# Assuming you are opening a new file
with open(input_file) as file:
lines = [x for x in reader(file) if x]
# for loop to parse the file by line
for line in lines:
name = [x.strip().lower() for x in line if x]
print(name) # Check the result
I really like this answer:
Copy-paste-ready version of @jibberia anwser:
def capitalize(line):
return ' '.join([s[0].upper() + s[1:] for s in line.split(' ')])
But some of the lines that I was sending split off some blank '' characters that caused errors when trying to do s[1:]. There is probably a better way to do this, but I had to add in a if len(s)>0, as in
return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])
Success story sharing
" ".join(w.capitalize() for w in s.split())
"e g 3b"
, the desired result would be"E G 3b"
. However,"e g 3b".title()
returns"E G 3B"
.In [2]: 'tEst'.title() Out[2]: 'Test'