Python: Is there a one line script to title case strings except for strings that start with a digit?
Asked Answered
I

5

7

The title() method works great, but I have a situation where there are strings that start with both words and numbers and I only want to titlecase the words in the string that do not begin with numbers.

The number of numbers can be variable, and there are not always numbers. Here is an example of each case.

"this is sparta".title() # This Is Sparta

"3rd sparta this is".title() # 3Rd Sparta This Is

"4545numbers start here".title() # "4545Numbers Start Here

I would like these to instead all be changed to:

"This Is Sparta"

"3rd Sparta This Is"

"4545numbers Start Here"

I am using a program that does not allow imports and I need to do this in one line. The only library I can use is re.

My preference would be to use a list comprehension to do this if possible.

Ignition answered 28/8, 2015 at 22:28 Comment(7)
Wait who down voted this???/ Why???? Why why whyIgnition
Why the no import clause? Standard library imports, such as re, should already be in sys.modules. Try doing import sys; sys.modules to see why.Postmark
I am not sure why. I am using python in an external program, not a custom script, which is why I can't use import. When is try to use string I get NameError: "String is not defined"Ignition
Surely it should have access to standard libraries though? What interpreter is this? I can understand the need for not loading non-standard libraries, but typically modules like re are loaded on startup. (For example, with Jython, CPython, and PyPy).Postmark
I would have to ask the developers. All the standard modules can be imported, but in a one line parameter, with no import statement I believe that string looks like just an undefined variable to the program.Ignition
Well then the re module, or a one-line, two statement clause should satisfy your needs, or the list comprehension answer given by @mVChr. You could do import re; re.sub...Postmark
What does "I am using python in an external program, not a custom script" mean? The program has to be calling Python somehow. You need to be very explicit here because you're doing something way off the wall, and no one is going to understand the restrictions without full details. Telling us what program it is would be a good start.Zigzag
T
4

Here's a simple list comprehension:

' '.join([word.capitalize() for word in your_string.split(' ')])

If you want to split on punctuation and other whitespace you'd probably have to use some sort of re function.

Trademark answered 28/8, 2015 at 22:37 Comment(4)
I will note that word[0].upper() + word[1:] is not quite equivalent to title. Example: 'ABCD'[0].upper() + 'ABCD'[1:] is 'ABCD', while 'ABCD'.title() is 'Abcd'. I think changing word[1:] to word[1:].lower() would fix it, but at that point, you may as well just capitalize instead.Zigzag
Eh, the string.capwords solution is best so who cares, right? :) EDIT: your string.capwords solution :)Trademark
Looks like the OP is specifying in edits/comments that for some bizarre reason they're having trouble with the imports, so your approach might actually be better in this case. ;)Zigzag
This is the answer I wanted. I guess I should have specified that I wanted to use a list comprehension. I could not use imports because the expressions are evaluated in Python contexts that are only one line.Ignition
Z
16

As it turns out, there's already a function that does this, string.capwords:

>>> import string
>>> string.capwords('1st foo bar bor1ng baz')
'1st Foo Bar Bor1ng Baz'
>>> string.capwords("3rd sparta this is")
'3rd Sparta This Is'

One thing to beware of: runs of whitespace will be collapsed into a single space, and leading and trailing whitespace will be removed. Notably, this means you'll lose line separators. You should split into lines first if you wish to preserve those.

Note that internally, it actually uses the capitalize method instead of title, but this appears to be what you want.

Zigzag answered 28/8, 2015 at 22:43 Comment(1)
@rcoyner Ironically, I only found it because I was looking up the documentation for split for your answer. lolZigzag
T
4

Here's a simple list comprehension:

' '.join([word.capitalize() for word in your_string.split(' ')])

If you want to split on punctuation and other whitespace you'd probably have to use some sort of re function.

Trademark answered 28/8, 2015 at 22:37 Comment(4)
I will note that word[0].upper() + word[1:] is not quite equivalent to title. Example: 'ABCD'[0].upper() + 'ABCD'[1:] is 'ABCD', while 'ABCD'.title() is 'Abcd'. I think changing word[1:] to word[1:].lower() would fix it, but at that point, you may as well just capitalize instead.Zigzag
Eh, the string.capwords solution is best so who cares, right? :) EDIT: your string.capwords solution :)Trademark
Looks like the OP is specifying in edits/comments that for some bizarre reason they're having trouble with the imports, so your approach might actually be better in this case. ;)Zigzag
This is the answer I wanted. I guess I should have specified that I wanted to use a list comprehension. I could not use imports because the expressions are evaluated in Python contexts that are only one line.Ignition
O
3

Regex solution.

In [19]: re.sub(r'\b(\w+)\b', lambda x: x.groups()[0].capitalize(), "3rd sparta this.is1", re.UNICODE)
Out[19]: '3rd Sparta This.Is1'

(see documentation on re.sub)

Openwork answered 28/8, 2015 at 22:44 Comment(0)
F
1

This could be another option:

  s = "3rd sparta this is"
  " ".join([si.title() if not (str.isdigit(si[0])) else si for si in s.split()])
Funicle answered 28/8, 2015 at 22:37 Comment(1)
This is actually exactly what I wanted.Ignition
S
0

Just set the first character to uppercase

string = string.split (' ')
for x in range (len(string)):
    try:
        string[x] = string[x][0].uppercase() + string [x][1:]
    except ValueError:
        pass
temp = ''
for word in string:
    temp += word + ' '
string = temp
string.title()
Supererogatory answered 28/8, 2015 at 22:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.