Làm thế nào để chuyển đổi chuỗi thành Title Case trong Python?


97

Thí dụ:

HILO -> Hilo
new york -> New York
SAN FRANCISCO -> San Francisco

Có thư viện hoặc cách tiêu chuẩn để thực hiện tác vụ này không?


16
Đó không phải là "CamelCase", đó là "Viết hoa"; bạn muốn cái nào
Andrew Marshall

13
camelCase giống như điều này.
Jonathan M

5
Ví dụ của bạn sử dụng PascalCase.
David Betz

Câu trả lời:


219

Tại sao không sử dụng titleNgay từ tài liệu:

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

Nếu bạn thực sự muốn PascalCase, bạn có thể sử dụng cái này:

>>> ''.join(x for x in 'make IT pascal CaSe'.title() if not x.isspace())
'MakeItPascalCase'

5
Tôi nghĩ chữ 'r' trong "They are" phải là chữ thường. Và 's' trong "Bill's" chắc chắn phải là chữ thường.
Daniel Fischer

3
@Daniel - Vấn đề đó được lưu ý trong tài liệu cho title: "Thuật toán sử dụng một định nghĩa đơn giản không phụ thuộc vào ngôn ngữ của một từ dưới dạng các nhóm các chữ cái liên tiếp. Định nghĩa này hoạt động trong nhiều ngữ cảnh nhưng nó có nghĩa là dấu nháy đơn trong các từ co và sở hữu tạo thành ranh giới từ, mà có thể không phải là kết quả mong muốn ". Một giải pháp khả thi là sử dụng câu trả lời của Laurence với regex r"['\w]+"để dấu nháy đơn không kết thúc một kết quả khớp (có thể thêm dấu câu bổ sung nếu cần).
Andrew Clark

18
Đối với bản ghi, một cách gọn gàng hơn để thực hiện ví dụ CamelCase cuối cùng là 'make IT camel CaSe'.title().replace(' ', '').
Henry Gomersall

15
Nếu bất kỳ ai khác cảm thấy như họ đang uống những viên thuốc điên rồ - thì đây là PascalCase, không phải camelCase.
Rob

4
Mã đẹp nhưng camelCase không bắt đầu bằng CHỮ HOA. Hãy thử điều này: def toCamel(s): ret = ''.join(x for x in s.title() if not x.isspace()) return ret[0].lower() + ret[1:] Cách sử dụng:toCamel("WRITE this in camelcase") 'writeThisInCamelcase'
Ron Kalian

22

Cái này sẽ luôn bắt đầu bằng chữ thường và cũng tách các ký tự không phải chữ và số:

def camelCase(st):
    output = ''.join(x for x in st.title() if x.isalnum())
    return output[0].lower() + output[1:]

8
def capitalizeWords(s):
  return re.sub(r'\w+', lambda m:m.group(0).capitalize(), s)

re.subcó thể nhận một hàm cho "thay thế" (thay vì chỉ một chuỗi, đây là cách sử dụng mà hầu hết mọi người dường như quen thuộc). Hàm repl này sẽ được gọi với một re.Matchđối tượng cho mỗi trận đấu của mẫu và kết quả (phải là một chuỗi) sẽ được sử dụng thay thế cho kết quả phù hợp đó.

Một phiên bản dài hơn của cùng một thứ:

WORD_RE = re.compile(r'\w+')

def capitalizeMatch(m):
  return m.group(0).capitalize()

def capitalizeWords(s):
  return WORD_RE.sub(capitalizeMatch, s)

Điều này sẽ biên dịch trước mẫu (thường được coi là dạng tốt) và sử dụng một hàm được đặt tên thay vì lambda.


cái này là khá gọn gàng, tôi đang cố gắng để có được đầu của tôi xung quanh hàm lambda, cảm ơn bạn đã giúp đỡ
bé hay mơ mộng

1
@JohnMachin Tôi chỉ hỏi vì tôi nghĩ rằng thêm một số giải thích sẽ làm cho câu trả lời của bạn đầy đủ hơn và tốt hơn.
NN

@Laurence Gonsalves lambda đang làm gì ở đây?
Zion

lambda đang làm gì ở đây? từ những gì tôi có thể giải mã và từ bạn giải thích. đây là những gì tôi đã hiểu. khi bạn sử dụng một hàm trong re.sub, mỗi hàm matchsẽ được chuyển cho hàm? và vì matchestrong biểu thức chính quy có nhóm. đó là lý do tại sao dòng này tồn tại lambda m:m.group(0).capitalize()?
Zion

@Zion vâng. Khi re.subđược cung cấp một có thể gọi (ví dụ: một hàm) làm "thay thế", nó sẽ chuyển đối tượng so khớp đến có thể gọi đó và mong đợi nhận lại một chuỗi mà nó thực sự sử dụng để thay thế. Nếu bạn thấy lambdas khó hiểu, "phiên bản dài hơn" thực hiện chính xác điều tương tự theo cách dài dòng hơn.
Laurence Gonsalves

5

Tại sao không viết một? Một cái gì đó như thế này có thể đáp ứng yêu cầu của bạn:

def FixCase(st):
    return ' '.join(''.join([w[0].upper(), w[1:].lower()]) for w in st.split())

cảm ơn, điều đó đã giúp hoàn toàn. Thật tệ, tôi đã không nghĩ đến việc viết một cái ngay từ đầu
daydreamer

5

Lưu ý: Tại sao tôi lại đưa ra một câu trả lời khác? Câu trả lời này dựa trên tiêu đề của câu hỏi và khái niệm rằng camelcase được định nghĩa là: một loạt các từ đã được nối (không có dấu cách!) Sao cho mỗi từ ban đầu bắt đầu bằng một ký tự viết hoa (phần còn lại là chữ thường) ngoại trừ từ đầu tiên của chuỗi (hoàn toàn là chữ thường). Ngoài ra, giả định rằng "tất cả các chuỗi" đề cập đến bộ ký tự ASCII; unicode sẽ không hoạt động với giải pháp này).

đơn giản

Với định nghĩa trên, hàm này

import re
word_regex_pattern = re.compile("[^A-Za-z]+")

def camel(chars):
  words = word_regex_pattern.split(chars)
  return "".join(w.lower() if i is 0 else w.title() for i, w in enumerate(words))

, khi được gọi, sẽ dẫn đến theo cách này

camel("San Francisco")  # sanFrancisco
camel("SAN-FRANCISCO")  # sanFrancisco
camel("san_francisco")  # sanFrancisco

ít đơn giản hơn

Lưu ý rằng nó không thành công khi được trình bày với một chuỗi có vỏ bọc lạc đà!

camel("sanFrancisco")   # sanfrancisco  <-- noted limitation

thậm chí ít đơn giản hơn

Lưu ý rằng nó không thành công với nhiều chuỗi unicode

camel("México City")    # mXicoCity     <-- can't handle unicode

Tôi không có giải pháp cho những trường hợp này (hoặc những trường hợp khác có thể được giới thiệu với một số sáng tạo). Vì vậy, như trong tất cả những thứ liên quan đến chuỗi, hãy che các trường hợp cạnh của bạn và chúc may mắn với unicode!


Làm thế nào bạn có thể xác định rằng một chuỗi là trường hợp Camel mà không biết nghĩa của câu? Trong ví dụ "ít đơn giản hơn" của bạn, "sanfRancisco" là trường hợp Camel cũng như "itSnotcaMelcAse".
Patrice Bernassola

Tôi đoán đầu vào của bạn có dấu nháy đơn hoặc dấu câu khác? Tôi nên lưu ý đầu vào không thành công khác. Chắc chắn là một bắt tốt. Đầu vào bạn đã cung cấp là gì?
Marc

1
Ý tôi là hơn một chuỗi ký tự không có khoảng trắng phải được coi là 1 từ. Bạn không thể trích xuất công việc từ nó mà không biết nghĩa của câu. Đặt "sanfRancisco" hoặc "itSnotcaMelcAse" làm đầu vào của camello () và bạn sẽ thấy rằng đầu ra sẽ giống nhau.
Patrice Bernassola

Ồ, tôi hiểu rồi - vâng, tôi nghĩ bạn đúng. Tôi quá thích giải pháp. Tôi sẽ cập nhật nó.
Marc

4

Thư viện tiềm năng: https://pypi.org/project/stringcase/

Thí dụ:

import stringcase
stringcase.camelcase('foo_bar_baz') # => "fooBarBaz"

Mặc dù có vấn đề là liệu nó có để lại khoảng trống hay không. (Các ví dụ cho thấy nó xóa khoảng trắng, nhưng có một vấn đề của trình theo dõi lỗi lưu ý rằng nó sẽ để lại chúng).


Heck vâng. Đang tìm kiếm một gói. Gói này cũng có snakecase và các chức năng chuyển đổi khác.
s2t2 19/07/19

1

chỉ cần sử dụng .title () và nó sẽ chuyển đổi chữ cái đầu tiên của mỗi từ thành chữ hoa, phần còn lại là nhỏ:

>>> a='mohs shahid ss'
>>> a.title()
'Mohs Shahid Ss'
>>> a='TRUE'
>>> b=a.title()
>>> b
'True'
>>> eval(b)
True

1

Tôi muốn thêm đóng góp nhỏ của tôi cho bài đăng này:

def to_camelcase(str):
  return ' '.join([t.title() for t in str.split()])

Trên thực tế, str.title () cũng giống như vậy và bạn đang tiết kiệm chi phí tính toán.
Auros132

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.