Bagaimana cara menggunakan huruf besar untuk setiap kata dalam sebuah string?


588
s = 'the brown fox'

... lakukan sesuatu di sini ...

s seharusnya :

'The Brown Fox'

Apa cara termudah untuk melakukan ini?

Jawaban:


990

The .title()metode string (baik ASCII atau Unicode baik-baik saja) melakukan hal ini:

>>> "hello world".title()
'Hello World'
>>> u"hello world".title()
u'Hello World'

Namun, perhatikan string dengan apostrof yang tertanam, seperti yang tercantum dalam dokumen.

Algoritme menggunakan definisi sederhana yang tidak tergantung pada bahasa sebagai kelompok huruf berurutan. Definisi ini berfungsi dalam banyak konteks tetapi itu berarti bahwa tanda kutip dalam kontraksi dan posesif membentuk batas kata, yang mungkin bukan hasil yang diinginkan:

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

56
Saya menghindari masalah posesif dengan sesuatu seperti" ".join(w.capitalize() for w in s.split())
mehtunguh

3
ini tidak aman untuk sebagian besar string karena setiap kata bahkan posesif akan menjadi huruf besar.

10
Ada masalah dengan string.title (). Ketika Anda menggunakan, misalnya, "e g 3b"hasil yang diinginkan adalah "E G 3b". Namun, "e g 3b".title()kembali "E G 3B".
Sören

7
Perlu diingat bahwa ini akan menyebabkan ini juga:In [2]: 'tEst'.title() Out[2]: 'Test'
Jonas Libbrecht

4
Jawaban yang bagus, dan komentar menegaskan bahwa dengan python tidak semuanya berlaku seperti yang Anda inginkan, tetapi selalu ada cara mudah untuk membuatnya. Cara paling mudah adalah sering mengimpor perpustakaan yang dibuat khusus, seperti python-titlecase
Aaron3468

189

The .title()Metode tidak dapat bekerja dengan baik,

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

Coba string.capwords()metode,

import string
string.capwords("they're bill's friends from the UK")
>>>"They're Bill's Friends From The Uk"

Dari dokumen python pada capwords :

Pisahkan argumen menjadi kata-kata menggunakan str.split (), huruf besar setiap kata menggunakan str.capitalize (), dan gabungkan kata-kata dengan huruf kapital menggunakan str.join (). Jika argumen kedua opsional tidak ada atau tidak ada, karakter spasi whites digantikan oleh spasi tunggal dan spasi spasi awal dan jejak dihapus, jika sep digunakan untuk membagi dan bergabung dengan kata-kata.


2
Capwords masih kurang dan tidak menangani sesuatu seperti "There once was a string with an 'that had words right after it and then closed'". Dengan contoh ini semua dunia kecuali thatdikapitalisasi seperti yang diharapkan. Hasilnya adalah"There Once Was A String With An 'that Had Words Right After It And Then Closed'"
devonbleibtrey

Namun, ini berfungsi lebih baik daripada title()untuk situasi normal. Dalam situasi saya, title()mengembalikan output yang buruk untuk nama dengan aksen atau dieresis, sementara capwords()menanganinya dengan benar.
houcros

1
Bagus, tetapi masih mengacaukan perbedaan "Inggris / Inggris"
Jonath P

1
@Chen Houwu, Inggris / UK adalah contoh counter sempurna. Bagaimana cara mencegah Python menurunkan huruf kapital yang ada menggunakan metode serupa?
h0r53

105

Hanya karena hal semacam ini menyenangkan bagi saya, berikut adalah dua solusi lagi.

Pisahkan menjadi kata-kata, tutup awal setiap kata dari grup yang dibagi, dan bergabung kembali. Ini akan mengubah ruang putih yang memisahkan kata-kata menjadi satu ruang putih, tidak peduli apa itu.

s = 'the brown fox'
lst = [word[0].upper() + word[1:] for word in s.split()]
s = " ".join(lst)

EDIT: Saya tidak ingat apa yang saya pikirkan ketika saya menulis kode di atas, tetapi tidak perlu membuat daftar eksplisit; kita dapat menggunakan ekspresi generator untuk melakukannya dengan gaya malas. Jadi, inilah solusi yang lebih baik:

s = 'the brown fox'
s = ' '.join(word[0].upper() + word[1:] for word in s.split())

Gunakan ekspresi reguler untuk mencocokkan awal string, atau kata-kata yang memisahkan spasi putih, ditambah karakter non-spasi tunggal; gunakan tanda kurung untuk menandai "kelompok yang cocok". Tulis fungsi yang mengambil objek pencocokan, dan mengembalikan grup pencocokan spasi putih tidak berubah dan grup pencocokan karakter non-spasi putih dalam huruf besar. Kemudian gunakan re.sub()untuk mengganti polanya. Yang ini tidak memiliki masalah tanda baca dari solusi pertama, juga tidak mengulangi ruang putih seperti solusi pertama saya. Yang ini menghasilkan hasil terbaik.

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"

Saya senang saya meneliti jawaban ini. Saya tidak punya ide yang re.sub()bisa berfungsi! Anda dapat melakukan pemrosesan nontrivial di dalam re.sub()untuk menghasilkan hasil akhir!


1
+1 untuk solusi menggunakan irisan. Saya membutuhkan sesuatu yang akan menggunakan huruf besar pertama tanpa mengubah huruf besar dari sisa kata-kata (misalnya Foo menjadi foo, tetapi FOO menjadi foo). Ini sempurna.
TomNysetvold

1
kapitalisasi mengembalikan karakter pertamanya dikapitalisasi dan sisanya
diturunkan

@Vanuan, kamu benar! Uraian string dokumen membuat saya berpikir semua yang dilakukan adalah huruf besar huruf pertama, tetapi Anda benar tentang apa yang sebenarnya dilakukannya. Saya akan mengedit jawabannya. Terima kasih atas bantuannya.
steveha

Ini tampaknya seperti apa string.capwords, menurut dokumentasi dalam jawaban Chen Houwu.
Adrian Keister

1
Sesuatu yang perlu diperhatikan dalam jawaban di atas, daripada menggunakan s.split (), saya pikir lebih baik menggunakan s.split (''). Ini karena jika string memiliki beberapa spasi ganda dan Anda ingin mempertahankan spasi ganda tersebut saat bergabung, s.plit ('') akan membantu Anda mempertahankan spasi sementara s.split () tidak akan
manpikin

21

Berikut ini ringkasan berbagai cara untuk melakukannya, mereka akan bekerja untuk semua input ini:

""           => ""       
"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"     

- Solusi paling sederhana adalah dengan memecah kalimat menjadi kata-kata dan huruf besar huruf pertama kemudian bergabung kembali:

# 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(' ')) 

- Jika Anda tidak ingin membagi string input menjadi kata-kata terlebih dahulu, dan menggunakan generator mewah:

# 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)) )

- Atau tanpa mengimpor itertools:

def cap_sentence(s):
  return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) for i, c in enumerate(s) )

- Atau Anda dapat menggunakan ekspresi reguler, dari jawaban steveha :

# 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)

Sekarang, ini adalah beberapa jawaban lain yang diposting, dan masukan yang tidak berfungsi seperti yang diharapkan jika kita menggunakan definisi kata sebagai awal kalimat atau apa pun setelah spasi kosong:

  return s.title()

# Undesired outputs: 
"foO baR"    => "Foo Bar"       
"foo's bar"  => "Foo'S Bar" 
"foo's1bar"  => "Foo'S1Bar"     
"foo 1bar"   => "Foo 1Bar"      

  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"      

menggunakan '' untuk pemisahan akan memperbaiki output kedua, tetapi capwords () masih tidak akan berfungsi untuk yang pertama

  return ' '.join(w.capitalize() for w in s.split(' '))    
  # or
  import string
  return string.capwords(s, ' ')

# Undesired outputs:
"foO baR"    => "Foo Bar"      

Hati-hati dengan beberapa ruang kosong

  return ' '.join(w[0].upper() + w[1:] for w in s.split())
# Undesired outputs:
"foo    bar" => "Foo Bar"                 

+1 untuk ringkasan yang komprehensif. Saya mencari cara untuk hanya menggunakan huruf besar kata setelah nomor (tidak setiap kata). Bisakah Anda membuat tambahan untuk jawaban Anda yang menunjukkan ini? Misalnya lower 123 upperharus kembali lower 123 Upper, di mana upperhuruf kapital ditulis mengikuti angka. Saya tahu ini melampaui lingkup pertanyaan OP tetapi tambahan yang bagus untuk jawaban Anda yang sudah luas. Terima kasih sebelumnya.
ProGrammer

Anda dapat memodifikasi beberapa metode di atas agar sesuai dengan kebutuhan Anda dalam kasus ini. Namun, saya tidak akan menambahkannya sebagai bagian dari jawaban karena bukan itu yang dicari kebanyakan orang. Saya akan menggunakan versi regex untuk itu, dan menggunakan "([0-9]+)(\s+.)"alih-alih "(^|\s)(\S)"(mencocokkan satu atau lebih angka, diikuti oleh satu atau lebih spasi, dan karakter apa pun setelah), atau "([0-9]+)(\s*.)"jika Anda ingin menggunakan huruf besar karakter setelah spasi 'nol atau lebih' setelah number
aljgom

Saya pasti akan memeriksanya, yang membuat saya berpikir tentang kasus khusus lain: Bagaimana Anda memodifikasi cuplikan di atas untuk mengambil string, misalnya WW1 - the great wardan WW1 - The Great Warbukannya keluaran Ww1 .... Lihat masalah dengan singkatan? Apakah Anda bersedia menambahkan sesuatu yang menunjukkan kasus ini? Saya telah bertanya-tanya tentang ini untuk sementara waktu sekarang dan tidak dapat memikirkan cara untuk melakukannya.
ProGrammer

Cara pertama yang disebutkan di atas tidak mengubah huruf yang sudah dikapitalisasi dalam string input, demikian juga WW1akan menampilkan sebagaiWW1
aljgom

15

Versi copy-paste-ready dari @jibberia anwser:

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))

2
Tidak perlu membuat daftar. str.joinmenerima generator.
warvariuc

@warvariuc bagaimana Anda mengubah kode ini untuk meningkatkan generator?
Konstantin Spirin

1
Hapus saja tanda kurung siku, seperti yang dilakukan di sini
warvariuc

1
Meskipun @warvariuc sempurna dalam menyebutkan bahwa joinmenerima gen exps, Dalam kasus str.joinkhususnya, umumnya lebih disukai untuk menggunakan pemahaman daftar. Ini karena joinmengulangi dua kali argumen, dan karenanya lebih cepat untuk menyediakan daftar siap pakai daripada generator.
Bhargav Rao

1
@BhargavRao mengapa str.joinperlu beralih dua kali atas argumen? Saya baru saja memeriksa - tidak. Padahal untuk urutan urutan kecil pemahamannya memang lebih cepat.
warvariuc

12

Mengapa Anda menyulitkan hidup Anda dengan bergabung dan untuk loop ketika solusinya sederhana dan aman ??

Lakukan ini:

string = "the brown fox"
string[0].upper()+string[1:]

2
Karena bisa ada beberapa kata.
Arnaud

1
Ya, tetapi seringkali saya hanya ingin menggunakan huruf besar untuk huruf pertama. Ini adalah cara untuk melakukan itu.
Menghapus

1
Bukankah Anda hanya akan menggunakan "the brown fox".capitalize()?
luckydonald

2
@luckydonald Karena mungkin saya tidak ingin berubah 'this is John'menjadi 'This is john'.
janek37

Bukan cara yang lebih baik untuk melakukan ini secara sederhana string.capitalize()(pada dasarnya menggemakan @ luckydonald)
Hassan Baig

10

Jika str.title () tidak berfungsi untuk Anda, lakukan huruf besar sendiri.

  1. Pisahkan string menjadi daftar kata
  2. Gunakan huruf besar untuk huruf pertama dari setiap kata
  3. Gabung kata-kata itu menjadi satu string

Satu-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"

Hapus contoh:

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)

1
Satu hal yang menarik dari solusi ini adalah Anda kehilangan spasi putih khusus. Mungkin tidak penting tergantung konteksnya.
mklauber

8

Andai saja Anda menginginkan huruf pertama:

>>> 'hello world'.capitalize()
'Hello world'

Tetapi untuk memanfaatkan setiap kata:

>>> 'hello world'.title()
'Hello World'

Karena hati 'hello New York'.capitalize()adalah'Hello new york'
user2314737

5

String kosong akan memunculkan Kesalahan jika Anda mengakses [1:], oleh karena itu saya akan menggunakan:

def my_uppercase(title):
    if not title:
       return ''
    return title[0].upper() + title[1:]

untuk huruf besar hanya huruf pertama.


Bukankah itu untuk apa str.capitalize?
Eugene Pakhomov

4
@Eugene, ya tapi sayangnya, huruf besar semua huruf kecil yang mungkin tidak diinginkan. : /
Wim Feijen

return title[:1].upper() + title[1:]juga akan mengurus masalah itu karena mengiris string kosong seperti itu akan memberikan 2 string kosong, bergabung bersama membuat string kosong yang dikembalikan
aljgom

3

Seperti yang ditunjukkan Mark, Anda harus menggunakan .title():

"MyAwesomeString".title()

Namun, jika ingin membuat huruf besar pertama di dalam template Django , Anda bisa menggunakan ini:

{{ "MyAwesomeString"|title }}

atau menggunakan variabel:

{{ myvar|title }}

3

Metode yang disarankan str.title () tidak berfungsi di semua kasus. Sebagai contoh:

string = "a b 3c"
string.title()
> "A B 3C"

dari pada "A B 3c" .

Saya pikir, lebih baik melakukan sesuatu seperti ini:

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'

1
namun kesalahan dapat muncul jika jumlah ruang yang memisahkannya tidak 1. Untuk referensi: masalah hackerrank
Divakar Rajesh

3

Meskipun semua jawabannya sudah memuaskan tetapi saya akan mencoba untuk menutupi 2 kasus tambahan bersama dengan semua kasus sebelumnya.

jika spasi tidak seragam dan Anda ingin mempertahankan yang sama

string = hello    world i  am    here.

jika semua string tidak dimulai dari huruf

string = 1 w 2 r 3g

Di sini Anda bisa menggunakan ini

def solve(s):
    a = s.split(' ')
    for i in range(len(a)):
        a[i]= a[i].capitalize()
    return ' '.join(a)

ini akan memberimu

output = Hello    World I  Am    Here
output = 1 W 2 R 3g

Saya harap ini tidak berlebihan.


2
Terima kasih telah menyoroti kasus ruang yang tidak seragam. Beberapa jawaban di atas menggunakan s.split () alih-alih s.split (''). Penting untuk dicatat bahwa untuk ruang yang tidak seragam, menggunakan s.split ('') akan memastikan bahwa ruang yang tidak seragam dipertahankan! Terima kasih lagi
manpikin

Ini berfungsi sempurna untuk kata-kata dengan spasi tidak rata atau kata-kata yang dimulai dengan beberapa digit. Terima kasih :)
Amresh Giri

2

Untuk menggunakan huruf besar ...

str = "this is string example....  wow!!!";
print "str.title() : ", str.title();

@ Gary02127 komentar, di bawah judul karya solusi dengan tanda kutip

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))

Gunakan fungsi yang ada memberikan eksekusi cepat dengan python.
Tejas Tank

Saya tidak terlalu menyukai judul (), karena tidak menangani apostrof. "Saya tidak bisa mengatakan" .title () memberikan "Saya Tidak Bisa Mengatakan"
Gary02127

@ Gary02127 Saya telah memperbarui jawaban, silakan lihat, bekerja sempurna dengan domain masalah Anda juga
Tejas Tank

1

Jangan mengabaikan kelestarian ruang putih. Jika Anda ingin memproses 'fred flinstone'dan mendapatkan 'Fred Flinstone'alih-alih 'Fred Flinstone', Anda telah merusak ruang putih Anda. Beberapa solusi di atas akan kehilangan ruang putih. Inilah solusi yang bagus untuk Python 2 dan 3 dan mempertahankan ruang putih.

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))

0

Fungsi cepat bekerja untuk 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.

0

Kapitalisasi string dengan spasi yang tidak seragam

Yah, saya mengerti ini adalah pertanyaan lama dan mungkin jawaban mungkin sudah hampir dihapus, tapi saya ingin menambahkan titik @Amit Gupta tentang ruang yang tidak seragam. Dari pertanyaan awal, kami ingin memanfaatkan setiap kata dalam string s = 'the brown fox'. Bagaimana jika string itu s = 'the brown fox'dengan spasi yang tidak seragam.

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)

.. kode Anda gagal mengkompensasi tab jika bukan spasi putih antara coklat dan rubah ;-)
ZF007

-1

** Jika Anda ingin berhemat **

 #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

-2

Saya sangat suka jawaban ini:

Versi copy-paste-ready dari @jibberia anwser:

def capitalize(line):
    return ' '.join([s[0].upper() + s[1:] for s in line.split(' ')])

Tetapi beberapa baris yang saya kirim memisahkan beberapa karakter kosong yang menyebabkan kesalahan ketika mencoba melakukan s [1:]. Mungkin ada cara yang lebih baik untuk melakukan ini, tetapi saya harus menambahkan jika if (s)> 0, seperti pada

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])

2
Ini terlalu rumit, bahkan Anda harus memeriksa panjangnya ?! tidak efisien.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.