Cách viết hoa chữ cái đầu tiên trong Chuỗi trong Ruby


134

Các upcasephương pháp viết hoa toàn bộ chuỗi, nhưng tôi cần phải tận dụng chỉ chữ cái đầu tiên.

Ngoài ra, tôi cần hỗ trợ một số ngôn ngữ phổ biến, như tiếng Đức và tiếng Nga.

Tôi phải làm nó như thế nào?


4
Xin lưu ý rằng một số ngôn ngữ có các ý tưởng khác nhau về chữ cái đầu tiên được viết hoa là gì. Ở Ailen, bạn làm những việc như "i mBaile Átha Cliath" ("ở Dublin") - chữ thường 'm', chữ hoa 'B'. (Xem en.wikipedia.org/wiki/Consonant_muting#Celtic_lacular nếu bạn tò mò về lý do tại sao Ailen sẽ làm điều đó và tại sao nó có ý nghĩa.)
James Moore

3
Và cũng cần lưu ý rằng #capitalize sẽ đánh dấu tất cả các chữ cái không phải là chữ cái đầu tiên ... không phải lúc nào cũng là điều bạn muốn. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

Câu trả lời:


260

Nó phụ thuộc vào phiên bản Ruby bạn sử dụng:

Ruby 2.4 trở lên:

Nó chỉ hoạt động, vì Ruby v2.4.0 hỗ trợ ánh xạ trường hợp Unicode:

"мария".capitalize #=> Мария

Ruby 2.3 trở xuống:

"maria".capitalize #=> "Maria"
"мария".capitalize #=> мария

Vấn đề là, nó không làm những gì bạn muốn, nó xuất ra марияthay vì Мария.

Nếu bạn đang sử dụng Rails, có một cách giải quyết dễ dàng:

"мария".mb_chars.capitalize.to_s # requires ActiveSupport::Multibyte

Nếu không, bạn sẽ phải cài đặt đá quý unicode và sử dụng nó như thế này:

require 'unicode'

Unicode::capitalize("мария") #=> Мария

Ruby 1.8:

Hãy chắc chắn sử dụng nhận xét ma thuật mã hóa :

#!/usr/bin/env ruby

puts "мария".capitalize

cho invalid multibyte char (US-ASCII), trong khi:

#!/usr/bin/env ruby
#coding: utf-8

puts "мария".capitalize

hoạt động không có lỗi, nhưng cũng thấy phần "Ruby 2.3 trở xuống" để viết hoa thực sự.


19
Lưu ý rằng rõ ràng "my API is great".capitalizesẽ tạo ra My api is greatmà có lẽ là hành vi không mong muốn. Vì vậy, câu trả lời này không thực sự trả lời câu hỏi vì anh ta chỉ muốn lá thư ĐẦU TIÊN chuyển sang chữ hoa và những người khác không bị ảnh hưởng.
Daniel AR Werner

55

viết hoa chữ cái đầu tiên của từ đầu tiên của chuỗi

"kirk douglas".capitalize
#=> "Kirk douglas"

viết hoa chữ cái đầu tiên của mỗi từ

Trong đường ray:

"kirk douglas".titleize
=> "Kirk Douglas"

HOẶC LÀ

"kirk_douglas".titleize
=> "Kirk Douglas"    

Trong hồng ngọc:

"kirk douglas".split(/ |\_|\-/).map(&:capitalize).join(" ") 
#=> "Kirk Douglas"

bên ngoài đường ray, nhưng vẫn muốn sử dụng phương thức tiêu đề

require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize

1
Upvote cho một giải pháp Ruby tinh khiết. Quá lười biếng để kích hoạt Rails đúng cách, và điều này đã tạo nên mánh khóe :)
illbzo1

19

Thật không may, máy móc không thể viết hoa / viết hoa / viết hoa đúng cách. Nó cần quá nhiều thông tin theo ngữ cảnh để máy tính có thể hiểu được.

Đó là lý do tại sao Ruby Stringlớp chỉ hỗ trợ vốn cho các ký tự ASCII, vì nó ít nhất phần nào được xác định rõ.

"Thông tin theo ngữ cảnh" nghĩa là gì?

Ví dụ, để viết hoa iđúng, bạn cần biết văn bản đó bằng ngôn ngữ nào. Ví dụ, tiếng Anh chỉ có hai is: capital Ikhông có dấu chấm và nhỏ icó dấu chấm. Nhưng Thổ Nhĩ Kỳ có bốn is: thủ đô Ikhông có dấu chấm, thủ đô İcó dấu chấm, nhỏ ıkhông có dấu chấm, nhỏ icó dấu chấm. Vì vậy, bằng tiếng Anh 'i'.upcase # => 'I'và tiếng Thổ Nhĩ Kỳ 'i'.upcase # => 'İ'. Nói cách khác: vì 'i'.upcasecó thể trả về hai kết quả khác nhau, tùy thuộc vào ngôn ngữ, rõ ràng không thể viết hoa một từ chính xác mà không biết ngôn ngữ của nó.

Nhưng Ruby không biết ngôn ngữ, nó chỉ biết mã hóa. Do đó, không thể viết hoa đúng chuỗi có chức năng tích hợp của Ruby.

Nó trở nên tệ hơn: ngay cả với biết ngôn ngữ, nó là đôi khi không thể làm vốn hóa đúng cách. Ví dụ, trong tiếng Đức, 'Maße'.upcase # => 'MASSE'( Maße là số nhiều của phép đo nghĩa Maß ). Tuy nhiên, (có nghĩa là khối lượng ). Vậy, là gì? Nói cách khác: viết hoa chính xác đòi hỏi Trí tuệ nhân tạo toàn diện.'Masse'.upcase # => 'MASSE''MASSE'.capitalize

Vì vậy, thay vì đôi khi đưa ra câu trả lời sai, Ruby chọn đôi khi không đưa ra câu trả lời nào cả , đó là lý do tại sao các ký tự không phải ASCII đơn giản bị bỏ qua trong các hoạt động viết hoa / viết hoa / viết hoa. (Tất nhiên cũng đọc kết quả sai, nhưng ít nhất nó cũng dễ kiểm tra.)


4
Xin lỗi, nhưng lập luận của bạn không giữ được nước. Không phải sự thật là Ruby chọn không đưa ra câu trả lời nào cả, Ruby luôn đưa ra một câu trả lời, điều này thường sai - ví dụ: "арар" ".upcase không bao giờ nên trả lại" ", không đúng trong bất kỳ ngữ cảnh nào. Và sự lạc quan của bạn về nhu cầu AI hoàn toàn không liên quan - không có gì ngăn cản việc giữ lại một mảng, nói ['I', '' '' cho 'i'.upcase và để người gọi quyết định cách viết hoa nào có liên quan trong một tình huống nhất định. Hiện tại việc xử lý chuyển đổi giữa chữ hoa và chữ thường của Ruby đã bị hỏng và đó là điều đó.
michau

2
-1 vì có một thủ đô Eszett . Sử dụng một số khu vực không chính thức hoàn toàn không thể dùng làm bằng chứng cho giải pháp đó chỉ có thể với AI.
Mike

15

Chà, chỉ để chúng tôi biết cách viết hoa chữ cái đầu tiên và để phần còn lại của chúng một mình, bởi vì đôi khi đó là những gì mong muốn:

['NASA', 'MHz', 'sputnik'].collect do |word|
  letters = word.split('')
  letters.first.upcase!
  letters.join
end

 => ["NASA", "MHz", "Sputnik"]

Gọi capitalizesẽ dẫn đến ["Nasa", "Mhz", "Sputnik"].


Cảm ơn bạn đúng như những gì tôi đang tìm kiếm, hữu ích cho việc chuyển đổi các tiêu đề thành 'trường hợp câu'
Good Lux

2
word[0] = word[0].upcase
David

@David. KHÔNG! Điều đó thay đổi giá trị của các từ trong mảng mà #collect được gọi. Đó là một tác dụng phụ xấu.
Huliax

Tôi đã chỉ ra một cách đơn giản hơn để viết hoa chữ cái đầu tiên của từ, thay thế 3 dòng bên trong của giải pháp này, điều mà tôi đã làm rõ bằng cách sử dụng wordbiến. Tất nhiên, nếu bạn có nhiều từ hơn, chỉ cần gọi chúng trên tất cả chúng! ;)words.map{|word| word[0] = word[0].upcase}
David

@David. Mã của bạn lên tới #capitalize!và không #capitalize. Cái sau trả về một Chuỗi mới trong khi cái trước sửa đổi bộ thu của phương thức (trong trường hợp này là bộ thu wordvà phương thức là #[]). Nếu bạn đã sử dụng mã của mình bên trong khối #collect thì cuối cùng bạn sẽ có hai mảng khác nhau có cùng các đối tượng Chuỗi trong mỗi khối (và Chuỗi sẽ được sửa đổi). Đó không phải là điều bạn thường muốn làm. Ngay cả khi bạn biết điều này, những người đọc khác cũng nên hiểu điều này.
Huliax

8

Đường ray 5+

Kể từ Active Support và Rails 5.0.0.beta4, bạn có thể sử dụng một trong cả hai phương pháp: String#upcase_firsthoặc ActiveSupport::Inflector#upcase_first.

"my API is great".upcase_first #=> "My API is great"
"мария".upcase_first           #=> "Мария"
"мария".upcase_first           #=> "Мария"
"NASA".upcase_first            #=> "NASA"
"MHz".upcase_first             #=> "MHz"
"sputnik".upcase_first         #=> "Sputnik"

Kiểm tra " Rails 5: Phương pháp upcase_first mới " để biết thêm thông tin.


3

Sử dụng capitalize. Từ tài liệu String :

Trả về một bản sao của str với ký tự đầu tiên được chuyển thành chữ hoa và phần còn lại thành chữ thường.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"

Chỉ sử dụng dấu chấm than nếu bạn muốn thay đổi chuỗi gốc.
Magnar

doh Cảm ơn, đã sửa lỗi của tôi.
jhwist

5
-1. OP đề cập rõ ràng văn bản tiếng Đức và tiếng Nga, trong đó ngụ ý các ký tự không phải ASCII. String#upcase(và cũng String#downcase) chỉ được xác định cho các ký tự ASCII.
Jörg W Mittag

1
Sử dụng Ruby 2.5.0 ngày hôm nay và String#upcasedường như hoạt động tốt trên các ký tự không phải ASCII. 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax

1
@Huliax Như đã đề cập trong câu trả lời được chấp nhận, đó chỉ là trường hợp kể từ Ruby 2.4.0 (được phát hành vào năm 2016).
nisetama

2

Bạn có thể sử dụng mb_chars. Điều này tôn trọng umlaute:

class String

  # Only capitalize first letter of a string
  def capitalize_first
    self[0] = self[0].mb_chars.upcase
    self
  end

end

Thí dụ:

"ümlaute".capitalize_first
#=> "Ümlaute"

0

Dưới đây là một cách khác để viết hoa mỗi từ trong một chuỗi. \wkhông khớp các ký tự Cyrillic hoặc các ký tự Latinh với dấu phụ nhưng [[:word:]]không. upcase, downcase, capitalize, Và swapcasekhông áp dụng cho các ký tự ASCII đến của Ruby 2.4.0 được phát hành vào năm 2016.

"aAa-BBB ä мария _a a_a".gsub(/\w+/,&:capitalize)
=> "Aaa-Bbb ä мария _a A_a"
"aAa-BBB ä мария _a a_a".gsub(/[[:word:]]+/,&:capitalize)
=> "Aaa-Bbb Ä Мария _a A_a"

[[:word:]] phù hợp với các nhân vật trong các thể loại này:

Ll (Letter, Lowercase)
Lu (Letter, Uppercase)
Lt (Letter, Titlecase)
Lo (Letter, Other)
Lm (Letter, Modifier)
Nd (Number, Decimal Digit)
Pc (Punctuation, Connector)

[[:word:]]khớp với tất cả 10 ký tự trong danh mục "Dấu câu, Trình kết nối" ( Pc):

005F _ LOW LINE
203F ‿ UNDERTIE
2040 ⁀ CHARACTER TIE
2054 ⁔ INVERTED UNDERTIE
FE33 ︳ PRESENTATION FORM FOR VERTICAL LOW LINE
FE34 ︴ PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
FE4D ﹍ DASHED LOW LINE
FE4E ﹎ CENTRELINE LOW LINE
FE4F ﹏ WAVY LOW LINE
FF3F _ FULLWIDTH LOW LINE

Đây là một cách khác để chỉ chuyển đổi ký tự đầu tiên của chuỗi thành chữ hoa:

"striNG".sub(/./,&:upcase)
=> "StriNG"
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.