Memanfaatkan hanya karakter pertama dari string dan biarkan yang lain sendiri? (Rel)

102

Saya mencoba membuat Rails memanfaatkan karakter pertama string, dan membiarkan yang lainnya apa adanya. Saya mengalami masalah saat "saya dari New York" diubah menjadi "Saya dari new york."

Metode apa yang akan saya gunakan untuk memilih karakter pertama?

Terima kasih

EDIT: Saya mencoba menerapkan apa yang disarankan macek, tetapi saya mendapatkan kesalahan "metode tidak terdefinisi" memanfaatkan " . Kode berfungsi dengan baik tanpa garis huruf kapital. Terima kasih untuk bantuannya!

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title[0] = self.title[0].capitalize
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with? 'You know you'
end

EDIT 2: Berhasil. Terima kasih untuk bantuannya!

EDIT 3: Tunggu, tidak, saya tidak ... Inilah yang saya miliki dalam model daftar saya.

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title.slice(0,1).capitalize + self.title.slice(1..-1)
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with?  'You know you'
end

EDIT 4: Mencoba edit macek, dan masih mendapatkan kesalahan metode `` capitalize '"yang tidak ditentukan . Apa yang mungkin saya lakukan salah?

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

EDIT 5: Ini aneh. Saya dapat menyingkirkan kesalahan metode tidak ditentukan dengan menggunakan baris di bawah ini. Masalahnya adalah sepertinya mengganti huruf pertama dengan angka. Misalnya, alih-alih menggunakan huruf besar y pada Anda , ini mengubah y menjadi 121

self.title[0] = title[0].to_s.capitalize
Daniel O'Connor
sumber
Berdasarkan EDIT 3, Anda harus memulai baris 2 dengan self.title = . Juga, pada semua 3 baris, Anda hanya perlu self.titledi sebelah kiri =(tanda sama dengan). Di tempat lain Anda bisa menggunakan title. Lihat edit jawaban saya sebagai contoh.
maček
2
Masalah di Edit4 adalah Anda hanya memiliki karakter - bukan lagi string - oleh karena itu ia tidak akan mengenali fungsi string "capitalize".
Taryn East
Masalah dengan Edit 5 adalah bahwa judul [0] adalah fixnum, jadi memanggil judul [0] .to_s hanya akan memberi Anda nomor karakter (yaitu 121 sebagai string: "121"). Anda dapat melakukan self.title [0] = title.first.capitalize jika Anda mau!
Nick
Saya menambahkan #upcase_first_case dan membuat permintaan tarik: github.com/rails/rails/pull/15319 . Jangan ragu untuk menambahkan tanggapan Anda di sana.
Aldo 'xoen' Giambelluca

Jawaban:

93

Titleize akan menggunakan huruf besar setiap kata. Kalimat ini terasa berat, tapi akan menjamin bahwa satu-satunya surat yang diubah adalah yang pertama.

new_string = string.slice(0,1).capitalize + string.slice(1..-1)

Memperbarui:

irb(main):001:0> string = "i'm from New York..."
=> "i'm from New York..."
irb(main):002:0> new_string = string.slice(0,1).capitalize + string.slice(1..-1)
=> "I'm from New York..."
Taryn East
sumber
Tunggu, masih belum berhasil. Alarm salah: / Saya rasa saya menerapkannya dengan salah.
Daniel O'Connor
1
Daniel - umumnya merupakan bentuk yang baik untuk "menerima" jawaban yang memecahkan masalah Anda. Anda dapat melakukan ini dengan mengklik "centang" di sebelah kiri jawaban. :)
Taryn East
1
Saya salah memahami pertanyaannya, jika tidak, saya ingin memberi Anda 1. Saya mencari .titleize, bukan .capitalize. Terima kasih Taryn!
Eric Wanchic
OOC - Mengapa hal itu menghentikan Anda untuk memberikan suara positif? Apakah saya menjawab pertanyaan pengepos asli dengan benar? Jika Anda berpikir demikian - maka beri suara positif. Tidak harus bergantung pada hal lain ... :)
Taryn East
2
Jadi, begini: s[0].capitalize + s[1..-1] if s.present?
Alex Escalante
126

Ini harus melakukannya:

title = "test test"     
title[0] = title[0].capitalize
puts title # "Test test"
Pascal Van Hecke
sumber
40
Atau lebih tepatnya,title[0] = title[0].capitalize
Jon Garvin
Ini adalah solusi yang sangat elegan.
Karew
1
@JonGarvin title [0] .capitalize tidak berfungsi (setidaknya dengan Ruby 1.8.7), karena title [0] mengembalikan Fixnum, dan capitalize mengharapkan string .. jadi menurut saya title.first.capitalize adalah cara untuk Pergilah.
Nick
2
malu kamu tidak bisatitle.first.capitalize!
Adam Waite
1
capitalizemengonversi semua huruf setelah huruf pertama menjadi huruf kecil, jadi ini tidak berfungsi untuk string yang disajikan dalam pertanyaan ("Saya dari New York").
Mark Schneider
57

Anda bisa menggunakan memanusiakan. Jika Anda tidak membutuhkan garis bawah atau huruf besar lainnya di baris teks Anda.

Memasukkan:

"i'm from New_York...".humanize

Keluaran:

"I'm from new york..."
Bartuzz
sumber
7
OP secara khusus ingin menghindari 'new york'
phatmann
Hmm memang, agak terlalu cepat dengan jawabanku.
Bartuzz
17
@Bartuzz Meskipun ini bukan yang diinginkan OP, inilah yang sebenarnya saya cari. Terima kasih!
Yetti
Namun new york akan menjadi ungrammatical sebagai kata benda yang tepat dan harus menggunakan ibu kota.
Shayne
Berhati-hatilah, humanizeadalah Rails, tepatnya metode ActiveSupport. Ruby biasa tidak bisa melakukan itu.
Penguin
51
str = "this is a Test"
str.sub(/^./, &:upcase)
# => "This is a Test"
Lasse Bunk
sumber
1
Ringkas dan elegan. Saya yakin ini harus menjadi jawaban teratas.
Chris
Saya setuju. Saya pikir ini harus menjadi jawaban yang diterima.
Garry Pettet
Satu kekhasan adalah bahwa sejak ^berarti permulaan baris, "\nfoo"menjadi "\nFoo". Itu mungkin bagus untuk sebagian besar kasus penggunaan. Karena ini a subdan bukan a gsub, itu masih hanya akan memperbesar satu huruf, bahkan dengan string multiline.
Henrik N
Bisa mendapatkan batasan di atas dengan menggunakan str.sub(/\S/, &:upcase), yang akan mencari karakter non-spasi pertama dan memperbesarnya.
Anthony Panozzo
39

Pada Rails 5.0.0.beta4 Anda dapat menggunakan String#upcase_firstmetode baru atau ActiveSupport::Inflector#upcase_firstmelakukannya. Periksa posting blog ini untuk info lebih lanjut.

pengguna1519240
sumber
Itu berita bagus! Saya berpikir apa yang bisa kita lakukan sekarang dan mungkin polyfill untuk Rails 4 akan menyenangkan.
hakunin
Perhatikan bahwa upcase_first dan tidak menangani aksen / karakter khusus, bahkan dengan mb_chars
user3033467
14

Solusi berorientasi objek:

class String
  def capitalize_first_char
    self.sub(/^(.)/) { $1.capitalize }
  end
end

Maka Anda bisa melakukan ini:

"i'm from New York".capitalize_first_char
tata krama
sumber
Setidaknya ada yang menulis solusi elegan dengan perluasan Stringkelas.
Dmitriy
@Dmitriy mengapa monyet menambal kelas string elegan?
Gerard Simpson
7
str.sub(/./, &:capitalize)
emlai
sumber
6

Edit 2

Saya tidak bisa meniru masalah Anda. Lanjutkan dan jalankan skrip Ruby asli ini. Ini menghasilkan keluaran tepat yang Anda cari, dan Rails mendukung semua metode ini. Jenis masukan apa yang bermasalah?

#!/usr/bin/ruby
def fixlistname(title)
  title = title.lstrip
  title += '...' unless title =~ /\.{3}$/
  title[0] = title[0].capitalize
  raise 'Title must start with "You know you..."' unless title =~ /^You know you/
  title
end

DATA.each do |title|
  puts fixlistname(title)
end

__END__
you know you something WITH dots ...
you know you something WITHOUT the dots
  you know you something with LEADING whitespace...
  you know you something with whitespace BUT NO DOTS
this generates error because it doesn't start with you know you

keluaran

You know you something WITH dots ...
You know you something WITHOUT the dots...
You know you something with LEADING whitespace...
You know you something with whitespace BUT NO DOTS...
RuntimeError: Title must start with "You know you..."

Edit

Berdasarkan hasil edit Anda, Anda dapat mencoba sesuatu seperti ini.

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

Asli

Ini akan berhasil

s = "i'm from New York"
s[0] = s[0].capitalize
#=> I'm from New York

Ketika mencoba menggunakan String#capitalizeseluruh string, Anda melihat I'm from new yorkkarena metode:

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

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"
maček
sumber
+1 karena saya tidak berpikir itu akan berhasil sampai saya mencobanya di pc saya :)
Jeriko
Hai, terima kasih atas bantuannya. Apa yang saya lakukan salah? Saya telah mengedit pertanyaan asli untuk memasukkan kode saya.
Daniel O'Connor
Saya menggunakan saran Taryn dan berhasil. Terima kasih atas bantuannya!
Daniel O'Connor
Hai, stackoverflow bilang Anda sudah mengedit, tapi saya tidak melihat ada yang berbeda?
Daniel O'Connor
6
my_string = "hello, World"
my_string.sub(/\S/, &:upcase) # => "Hello, World"
Pavel Pravosud
sumber
Tidak gagal jika my_string kosong! Bagus. Inilah yang saya butuhkan.
Huliax
4

Sebagian besar jawaban ini mengedit string pada tempatnya, saat Anda hanya memformat untuk keluaran tampilan, Anda mungkin tidak ingin mengubah string yang mendasari sehingga Anda dapat menggunakan tapsetelah a dupuntuk mendapatkan salinan yang diedit

'test'.dup.tap { |string| string[0] = string[0].upcase }
Paul.s
sumber
3

Jika dan hanya jika OP ingin melakukan monkey patching pada objek String, maka ini dapat digunakan

class String
  # Only capitalize first letter of a string
  def capitalize_first
    self.sub(/\S/, &:upcase)
  end
end

Sekarang gunakan:

"i live in New York".capitalize_first #=> I live in New York
JVK
sumber
2

Versi yang lebih pendek bisa jadi:

s = "i'm from New York..."
s[0] = s.capitalize[0]
Saim
sumber
2

Tidak ada yang menyebutkan gsub, yang memungkinkan Anda melakukan ini secara ringkas.

string.gsub(/^([a-z])/) { $1.capitalize }

Contoh:

 > 'caps lock must go'.gsub(/^(.)/) { $1.capitalize }
=> "Caps lock must go"
mahemoff
sumber
1

Mungkin cara termudah.

s = "test string"
s[0] = s[0].upcase
# => "Test string"
Lukas Baliak
sumber
1

Perhatikan bahwa jika Anda perlu berurusan dengan karakter multi-byte, misalnya jika Anda harus menginternasionalkan situs Anda, s[0] = ...solusinya tidak akan cukup. Pertanyaan Stack Overflow ini menyarankan penggunaan gem unicode-util

Ruby 1.9: Bagaimana saya bisa melakukan upcase & downcase multibyte string dengan benar?

EDIT

Sebenarnya cara yang lebih mudah untuk setidaknya menghindari pengkodean string yang aneh adalah dengan hanya menggunakan String # mb_chars :

s = s.mb_chars
s[0] = s.first.upcase
s.to_s
keindahan depan
sumber
0

Bagaimana dengan metode klasifikasi pada string?

'somESTRIng'.classify

keluaran:

#rails => 'SomESTRIng'
mArtinko5MB
sumber
1
Ini melakukan banyak hal tambahan, seperti menyanyikan kata-kata. "hello worlds".classify # => "Hello world"
Pavel Pravosud
-3
string = "i'm from New York"
string.split(/\s+/).each{ |word,i| word.capitalize! unless i > 0 }.join(' ')
# => I'm from New York
Jeriko
sumber
Kelihatannya begitu. Saya baru mengenal ruby, dan jawaban lain tidak benar-benar melakukan apa yang diminta OP, jadi saya membuatnya berfungsi: D Koreksi saya jika saya salah, tetapi AFAIK memodifikasi string dengan mengubah string [i] tidak bekerja dalam banyak bahasa?
Jeriko
3
ini adalah pertanyaan khusus Ruby. Tidak masalah jika string[i]tidak berfungsi dalam bahasa lain. Harap bantu agar StackOverflow bebas dari jenis jawaban yang diretas ini. Kita tidak bisa mengatakan RTFM, tetapi bahkan cepat melirik Stringdocs akan telah membantu menghindari jawaban seperti ini ...
Macek