Cara menggunakan huruf besar untuk huruf pertama dalam String di Ruby

134

The upcaseMetode mengkapitalisasi seluruh string, tapi aku harus memanfaatkan hanya huruf pertama.

Juga, saya perlu mendukung beberapa bahasa populer, seperti Jerman dan Rusia.

Bagaimana saya melakukannya?

Antonal
sumber
4
Ketahuilah bahwa beberapa bahasa memiliki gagasan berbeda tentang huruf apa yang pertama kali ditulis dalam huruf kapital. Di Irlandia, Anda melakukan hal-hal seperti "i mBaile Átha Cliath" ("di Dublin") - huruf kecil 'm', huruf besar 'B'. (Lihat en.wikipedia.org/wiki/Consonant_mutation#Celtic_languages jika Anda penasaran tentang mengapa orang Irlandia melakukan hal itu dan mengapa hal itu masuk akal.)
James Moore
3
Perlu diketahui juga bahwa #capitalize akan menurunkan semua huruf yang bukan huruf pertama ... yang tidak selalu seperti yang Anda inginkan. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

Jawaban:

260

Itu tergantung pada versi Ruby yang Anda gunakan:

Ruby 2.4 dan lebih tinggi:

Ini hanya berfungsi, karena Ruby v2.4.0 mendukung pemetaan kasus Unicode:

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

Ruby 2.3 dan lebih rendah:

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

Masalahnya adalah, itu hanya tidak melakukan apa yang Anda inginkan, itu menghasilkan марияbukan Мария.

Jika Anda menggunakan Rails ada solusi mudah:

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

Jika tidak, Anda harus menginstal permata unicode dan menggunakannya seperti ini:

require 'unicode'

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

Ruby 1.8:

Pastikan untuk menggunakan komentar sihir pengkodean :

#!/usr/bin/env ruby

puts "мария".capitalize

memberi invalid multibyte char (US-ASCII), sementara:

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

puts "мария".capitalize

berfungsi tanpa kesalahan, tetapi juga lihat bagian "Ruby 2.3 dan lebih rendah" untuk huruf besar nyata.

Alberto Santini
sumber
19
Perhatikan bahwa tampaknya "my API is great".capitalizeakan menghasilkan My api is greatperilaku yang mungkin tidak diinginkan. Jadi jawaban ini tidak benar-benar menjawab pertanyaan karena ia hanya ingin surat PERTAMA beralih ke huruf besar dan yang lainnya tidak tersentuh.
Daniel AR Werner
55

kapitalisasi huruf pertama dari kata pertama dari string

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

kapitalisasi huruf pertama dari setiap kata

Di rel:

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

ATAU

"kirk_douglas".titleize
=> "Kirk Douglas"    

Dalam ruby:

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

di luar rel, tetapi masih ingin menggunakan metode memberi judul

require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize
boulder_ruby
sumber
1
Suara positif untuk solusi Ruby murni. Terlalu malas untuk menjalankan Rails dengan benar, dan ini berhasil :)
illbzo1
19

Sayangnya, tidak mungkin bagi mesin untuk melakukan huruf besar / huruf kecil / huruf besar dengan benar. Perlu terlalu banyak informasi kontekstual untuk dipahami oleh komputer.

Itu sebabnya Stringkelas Ruby hanya mendukung huruf besar untuk karakter ASCII, karena setidaknya ada beberapa definisi yang cukup jelas.

Apa yang saya maksud dengan "informasi kontekstual"?

Misalnya, untuk imenggunakan huruf besar dengan benar, Anda perlu mengetahui bahasa mana teks tersebut berada. Bahasa Inggris, misalnya, hanya memiliki dua is: modal Itanpa titik dan kecil idengan titik. Tetapi Turki memiliki empat is: modal Itanpa titik, modal İdengan titik, kecil ıtanpa titik, kecil idengan titik. Jadi, dalam bahasa Inggris 'i'.upcase # => 'I'dan Turki 'i'.upcase # => 'İ'. Dengan kata lain: karena 'i'.upcasedapat mengembalikan dua hasil yang berbeda, tergantung pada bahasanya, jelas mustahil untuk menggunakan huruf besar dengan benar tanpa mengetahui bahasanya.

Tapi Ruby tidak tahu bahasa, hanya tahu penyandian. Oleh karena itu, mustahil untuk membuat huruf kapital dengan benar dengan fungsionalitas bawaan Ruby.

Semakin buruk: bahkan dengan mengetahui bahasa, kadang-kadang mustahil untuk melakukan huruf besar dengan benar. Misalnya, dalam bahasa Jerman, 'Maße'.upcase # => 'MASSE'( Maße adalah jamak dari pengukuran makna Maß ). Namun, (artinya massa ). Jadi apa ? Dengan kata lain: penggunaan huruf kapital yang benar membutuhkan Intelegensi Buatan yang lengkap.'Masse'.upcase # => 'MASSE''MASSE'.capitalize

Jadi, alih-alih kadang-kadang memberikan jawaban yang salah, Ruby memilih untuk kadang-kadang tidak memberikan jawaban sama sekali , itulah sebabnya karakter non-ASCII diabaikan begitu saja dalam operasi huruf kecil / huruf besar / huruf besar. (Yang tentu saja juga membacakan hasil yang salah, tetapi setidaknya mudah untuk memeriksa.)

Jörg W Mittag
sumber
4
Maaf, argumentasi Anda tidak tahan. Tidak benar bahwa Ruby memilih untuk tidak memberikan jawaban sama sekali, Ruby selalu memberikan jawaban, yang sering salah - mis. "Мария" .upcase tidak boleh mengembalikan "мария", yang tidak benar dalam konteks apa pun. Dan penyimpangan Anda tentang perlunya AI sama sekali tidak relevan - tidak ada yang mencegah huruf besar mempertahankan array, katakan ['I', 'İ'] untuk 'i'.upcase, dan biarkan penelepon memutuskan kapitalisasi mana yang relevan dalam situasi tertentu. Saat ini penanganan konversi Ruby antara huruf besar dan kecil rusak, dan hanya itu.
michau
2
-1 karena ada modal Eszett . Menggunakan beberapa area yang tidak diformalkan sepenuhnya tidak dapat berfungsi sebagai bukti bahwa solusi hanya dimungkinkan dengan AI.
Mike
15

Ya, supaya kita tahu bagaimana menggunakan huruf besar hanya untuk huruf pertama dan membiarkan sisanya, karena kadang-kadang itulah yang diinginkan:

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

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

Panggilan capitalizeakan menghasilkan ["Nasa", "Mhz", "Sputnik"].

Huliax
sumber
Terima kasih apa yang saya cari, berguna untuk mengubah judul menjadi 'kalimat kasus'
Good Lux
2
word[0] = word[0].upcase
David
@ David. TIDAK! Itu mengubah nilai kata-kata dalam array yang dipanggil #collect. Itu adalah efek samping yang buruk.
Huliax
Saya menunjukkan cara yang lebih sederhana untuk memanfaatkan huruf pertama dari sebuah kata, mengganti 3 baris dalam solusi ini, yang saya perjelas dengan menggunakan wordvariabel. Tentu saja, jika Anda memiliki lebih banyak kata, panggil saja semuanya! ;)words.map{|word| word[0] = word[0].upcase}
David
@ David. Kode Anda berjumlah #capitalize!dan tidak #capitalize. Yang terakhir mengembalikan String baru sementara yang pertama memodifikasi penerima metode (dalam hal ini penerima worddan metode #[]). Jika Anda menggunakan kode Anda di dalam blok #collect maka Anda akan berakhir dengan dua array yang berbeda dengan objek String yang sama di masing-masing (dan Strings akan dimodifikasi). Itu bukan sesuatu yang biasanya ingin Anda lakukan. Bahkan jika Anda mengetahui hal ini, pembaca lain harus memahami ini.
Huliax
8

Rails 5+

Pada Dukungan Aktif dan Rails 5.0.0.beta4 Anda dapat menggunakan salah satu dari kedua metode: String#upcase_firstatau 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"

Periksa " Rails 5: New upcase_first Method " untuk info lebih lanjut.

pengguna1519240
sumber
3

Gunakan capitalize. Dari dokumentasi String :

Mengembalikan salinan str dengan karakter pertama dikonversi menjadi huruf besar dan sisanya menjadi huruf kecil.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"
jhwist
sumber
Gunakan hanya tanda seru jika Anda ingin string asli diubah.
Magnar
doh Terima kasih, perbaiki kesalahan saya.
jhwist
5
-1. OP secara eksplisit menyebutkan teks Jerman dan Rusia, yang menyiratkan karakter non-ASCII. String#upcase(dan juga String#downcase) hanya ditentukan untuk karakter ASCII.
Jörg W Mittag
1
Menggunakan Ruby 2.5.0 hari ini dan String#upcasetampaknya berfungsi dengan baik pada karakter non-ASCII. 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax
1
@Huliax Seperti yang disebutkan dalam jawaban yang diterima, itu hanya berlaku sejak Ruby 2.4.0 (yang dirilis pada 2016).
nisetama
2

Anda bisa menggunakannya mb_chars. Ini menghormati umlaute:

class String

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

end

Contoh:

"ümlaute".capitalize_first
#=> "Ümlaute"
dahak
sumber
0

Di bawah ini adalah cara lain untuk memanfaatkan setiap kata dalam string. \wtidak cocok dengan karakter Cyrillic atau karakter Latin dengan diakritik tetapi [[:word:]]tidak. upcase, downcase, capitalize, Dan swapcasetidak berlaku untuk karakter non-ASCII sampai Ruby 2.4.0 yang dirilis pada tahun 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:]] cocok dengan karakter dalam kategori ini:

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

[[:word:]]cocok dengan semua 10 karakter dalam kategori "Tanda Baca, Konektor" ( 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

Ini adalah cara lain untuk hanya mengonversi karakter pertama dari string menjadi huruf besar:

"striNG".sub(/./,&:upcase)
=> "StriNG"
nisetama
sumber