วิธีใช้อักษรตัวพิมพ์ใหญ่ตัวแรกใน String in Ruby


139

upcaseวิธีการใช้ประโยชน์สตริงทั้งหมด แต่ฉันต้องการที่จะลงทุนเพียงตัวอักษรตัวแรก

นอกจากนี้ฉันต้องรองรับภาษายอดนิยมหลายภาษาเช่นเยอรมันและรัสเซีย

ฉันต้องทำอย่างไร?


4
โปรดทราบว่าบางภาษามีแนวคิดที่แตกต่างกันเกี่ยวกับอักษรตัวแรกที่จะใช้เป็นตัวพิมพ์ใหญ่ ในภาษาไอริชคุณทำสิ่งต่างๆเช่น "i mBaile Átha Cliath" ("ในดับลิน") - ตัวพิมพ์เล็ก "m" ตัวพิมพ์ใหญ่ "B" (ดูen.wikipedia.org/wiki/Consonant_mutation#Celtic_languagesหากคุณสงสัยว่าทำไมชาวไอริชถึงทำเช่นนั้นและทำไมจึงสมเหตุสมผล)
เจมส์มัวร์

4
และโปรดทราบด้วยว่า #capitalize จะพิมพ์ตัวพิมพ์เล็กทั้งหมดซึ่งไม่ใช่ตัวอักษรตัวแรก ... ซึ่งไม่ใช่สิ่งที่คุณต้องการเสมอไป ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

คำตอบ:


264

ขึ้นอยู่กับรุ่น Ruby ที่คุณใช้:

Ruby 2.4 และสูงกว่า:

มันใช้งานได้เนื่องจากRuby v2.4.0รองรับ Unicode case mapping:

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

Ruby 2.3 และต่ำกว่า:

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

ปัญหาคือมันก็ไม่ได้ทำในสิ่งที่คุณต้องการให้มันจะออกผลลัพธ์แทนмарияМария

หากคุณใช้ Rails มีวิธีแก้ปัญหาง่ายๆ:

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

มิฉะนั้นคุณจะต้องติดตั้งUnicode gem และใช้งานในลักษณะนี้:

require 'unicode'

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

รูบี้ 1.8:

อย่าลืมใช้ความคิดเห็นเกี่ยวกับการเข้ารหัสมายากล:

#!/usr/bin/env ruby

puts "мария".capitalize

ให้invalid multibyte char (US-ASCII)ในขณะที่:

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

puts "мария".capitalize

ทำงานได้โดยไม่มีข้อผิดพลาด แต่ยังดูส่วน "Ruby 2.3 และต่ำกว่า" สำหรับการใช้อักษรตัวพิมพ์ใหญ่จริง


21
สังเกตว่า"my API is great".capitalizeจะก่อให้เกิดMy api is greatพฤติกรรมที่ไม่พึงปรารถนา ดังนั้นคำตอบนี้ไม่ได้ตอบคำถามอย่างแท้จริงเนื่องจากเขาต้องการให้ตัวอักษร FIRST เปลี่ยนเป็นตัวพิมพ์ใหญ่และอื่น ๆ โดยไม่ถูกแตะต้อง
Daniel AR Werner

55

อักษรตัวแรกของคำแรกของสตริงเป็นตัวพิมพ์ใหญ่

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

ใช้อักษรตัวแรกของแต่ละคำเป็นตัวพิมพ์ใหญ่

ในราง:

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

หรือ

"kirk_douglas".titleize
=> "Kirk Douglas"    

ในทับทิม:

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

นอกราง แต่ยังต้องการใช้เมธอด titleize

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

1
โหวตให้โซลูชัน Ruby ที่บริสุทธิ์ ขี้เกียจเกินไปที่จะยิง Rails ให้เหมาะสมและนี่ก็เป็นเคล็ดลับ :)
illbzo1

19

น่าเสียดายที่เป็นไปไม่ได้ที่เครื่องจะขึ้น / ลง / ใช้ตัวพิมพ์ใหญ่ มันต้องการข้อมูลเชิงบริบทมากเกินไปสำหรับคอมพิวเตอร์ที่จะเข้าใจ

นั่นเป็นเหตุผลที่Stringคลาสของ Ruby รองรับเฉพาะอักษรตัวพิมพ์ใหญ่สำหรับอักขระ ASCII เนื่องจากอย่างน้อยก็มีการกำหนดไว้อย่างดี

"ข้อมูลบริบท" หมายถึงอะไร

ตัวอย่างเช่นในการใช้อักษรตัวพิมพ์ใหญ่iอย่างถูกต้องคุณจำเป็นต้องทราบว่าข้อความนั้นอยู่ในภาษาใดตัวอย่างเช่นภาษาอังกฤษมีเพียงสองis: capital ที่Iไม่มีจุดและขนาดเล็กที่iมีจุด แต่ภาษาตุรกีมีสี่is: capital Iwithout a dot, capital İwith a dot, small ıwithout a dot, small iwith a dot ดังนั้นในภาษาอังกฤษและตุรกี'i'.upcase # => 'I' 'i'.upcase # => 'İ'กล่าวอีกนัยหนึ่ง: เนื่องจาก'i'.upcaseสามารถส่งคืนผลลัพธ์ที่แตกต่างกันสองรายการขึ้นอยู่กับภาษาจึงเป็นไปไม่ได้ที่จะใช้อักษรตัวพิมพ์ใหญ่อย่างถูกต้องโดยไม่ต้องรู้ภาษา

แต่รูบี้ไม่รู้ภาษารู้แค่การเข้ารหัสเท่านั้น ดังนั้นจึงเป็นไปไม่ได้ที่จะใช้ประโยชน์จากสตริงอย่างถูกต้องด้วยฟังก์ชันในตัวของ Ruby

จะได้รับแย่: แม้จะมีการรู้ภาษาที่บางครั้งก็เป็นไปไม่ได้ที่จะทำเงินทุนของ บริษัท อย่างถูกต้อง ตัวอย่างเช่นในภาษาเยอรมัน'Maße'.upcase # => 'MASSE'( Maßeเป็นพหูพจน์ของการวัดความหมายของMaß ) อย่างไรก็ตาม(หมายถึงมวล ) แล้วคืออะไร? กล่าวอีกนัยหนึ่ง: การใช้อักษรตัวพิมพ์ใหญ่อย่างถูกต้องจำเป็นต้องใช้ปัญญาประดิษฐ์เต็มรูปแบบ'Masse'.upcase # => 'MASSE''MASSE'.capitalize

ดังนั้นแทนที่จะบางครั้งการให้คำตอบที่ผิดทับทิมเลือกที่จะให้บางครั้งไม่มีคำตอบที่ทุกคนซึ่งเป็นเหตุผลที่อักขระที่ไม่ใช่ ASCII เพียงแค่ได้รับการละเว้นใน downcase / upcase / ประโยชน์การดำเนินงาน (ซึ่งแน่นอนว่าอ่านผลลัพธ์ผิดด้วย แต่อย่างน้อยก็ตรวจสอบได้ง่าย)


4
ขออภัยการโต้แย้งของคุณไม่ถือน้ำ ไม่เป็นความจริงที่ Ruby เลือกที่จะไม่ให้คำตอบเลย Ruby มักจะให้คำตอบซึ่งมักจะผิดเสมอเช่น "мария" .upcase ไม่ควรส่งคืน "мария" ซึ่งไม่ถูกต้องในบริบทใด ๆ และการพูดนอกเรื่องของคุณเกี่ยวกับความจำเป็นในการใช้ AI นั้นไม่เกี่ยวข้องเลย - ไม่มีสิ่งใดที่ขัดขวางการเก็บอาร์เรย์ของอัพเคสได้โดยพูดว่า ['I', 'İ'] สำหรับ 'i'.upcase และปล่อยให้ผู้โทรตัดสินใจว่าตัวพิมพ์ใหญ่ใดที่เกี่ยวข้อง ในสถานการณ์ที่กำหนด ปัจจุบันการจัดการการแปลงระหว่างตัวพิมพ์ใหญ่และตัวพิมพ์เล็กของ Ruby นั้นเสียและนั่นแหล่ะ
michau

2
-1 เนื่องจากมีเงินทุนEszett การใช้พื้นที่ที่ไม่เป็นทางการอย่างสมบูรณ์บางส่วนไม่สามารถใช้เป็นหลักฐานยืนยันว่าโซลูชันนั้นเป็นไปได้ด้วย AI เท่านั้น
Mike

17

ดังนั้นเราจึงรู้วิธีใช้ตัวพิมพ์ใหญ่เพียงตัวอักษรตัวแรกและปล่อยให้ส่วนที่เหลืออยู่คนเดียวเพราะบางครั้งนั่นคือสิ่งที่ต้องการ:

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

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

โทรจะส่งผลให้capitalize["Nasa", "Mhz", "Sputnik"]


ขอบคุณสิ่งที่ฉันกำลังมองหาซึ่งมีประโยชน์สำหรับการแปลงหัวเรื่องเป็น 'กรณีประโยค'
Good Lux

2
word[0] = word[0].upcase
เดวิด

@ เดวิด. ไม่! ซึ่งจะเปลี่ยนค่าของคำในอาร์เรย์ที่เรียก #collect นั่นคือผลข้างเคียงที่ไม่ดี
Huliax

ฉันกำลังแสดงวิธีที่ง่ายกว่าในการใช้อักษรตัวพิมพ์ใหญ่ตัวแรกของคำโดยแทนที่ 3 บรรทัดด้านในของโซลูชันนี้ซึ่งฉันได้อธิบายให้ชัดเจนโดยใช้wordตัวแปร แน่นอนว่าหากคุณมีคำศัพท์มากกว่านี้ก็เพียงแค่เรียกพวกเขาทั้งหมด! ;)words.map{|word| word[0] = word[0].upcase}
เดวิด

@ เดวิด. รหัสของคุณจะมีจำนวนไม่#capitalize! #capitalizeส่วนหลังส่งคืนสตริงใหม่ในขณะที่อดีตปรับเปลี่ยนผู้รับของวิธีการ (ในกรณีนี้คือตัวรับwordและวิธีการคือ#[]) หากคุณใช้รหัสของคุณภายในบล็อก #collect คุณจะได้อาร์เรย์สองอาร์เรย์ที่แตกต่างกันโดยมีอ็อบเจ็กต์ String เดียวกันในแต่ละอาร์เรย์ (และสตริงจะได้รับการแก้ไข) นั่นไม่ใช่สิ่งที่คุณต้องการทำตามปกติ แม้ว่าคุณจะทราบเรื่องนี้ แต่ผู้อ่านคนอื่น ๆ ก็ควรเข้าใจสิ่งนี้
Huliax

12

ราง 5+

ในขณะที่ Active Support และ Rails 5.0.0.beta4 คุณสามารถใช้หนึ่งในทั้งสองวิธี: String#upcase_firstหรือ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"

ตรวจสอบ " Rails 5: New upcase_first Method " สำหรับข้อมูลเพิ่มเติม


3

ใช้capitalize. จากเอกสารString :

ส่งคืนสำเนาของ str ที่มีอักขระตัวแรกที่แปลงเป็นตัวพิมพ์ใหญ่และส่วนที่เหลือเป็นตัวพิมพ์เล็ก

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

ใช้เครื่องหมายอัศเจรีย์หากคุณต้องการเปลี่ยนสตริงเดิมเท่านั้น
Magnar

DOHขอบคุณคงผิดพลาดของฉัน
jhwist

5
-1. OP กล่าวถึงข้อความภาษาเยอรมันและรัสเซียอย่างชัดเจนซึ่งหมายถึงอักขระที่ไม่ใช่ ASCII String#upcase(และString#downcase) กำหนดไว้สำหรับอักขระ ASCII เท่านั้น
Jörg W Mittag

1
วันนี้ใช้ Ruby 2.5.0 และString#upcaseดูเหมือนว่าจะทำงานได้ดีกับอักขระที่ไม่ใช่ ASCII 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax

1
@Huliax ดังที่ได้กล่าวไว้ในคำตอบที่ได้รับการยอมรับนั่นเป็นเพียงกรณีนี้ตั้งแต่ Ruby 2.4.0 (ซึ่งเปิดตัวในปี 2559)
nisetama

2

คุณสามารถใช้mb_chars. สิ่งนี้เคารพ umlaute:

class String

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

end

ตัวอย่าง:

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

2

ด้านล่างนี้เป็นอีกวิธีหนึ่งในการใช้ตัวพิมพ์ใหญ่ในแต่ละคำในสตริง \wไม่ตรงกับอักขระซิริลลิกหรืออักขระละตินที่มีการกำกับเสียง แต่[[:word:]]ตรงกับ upcase, downcase, capitalizeและswapcaseไม่ได้นำไปใช้กับตัวละครที่ไม่ใช่ ASCII จนกว่าทับทิม 2.4.0 ซึ่งได้รับการปล่อยตัวในปี 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:]] จับคู่อักขระในหมวดหมู่เหล่านี้:

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

[[:word:]]จับคู่อักขระทั้ง 10 ตัวใน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

นี่เป็นอีกวิธีในการแปลงเฉพาะอักขระตัวแรกของสตริงเป็นตัวพิมพ์ใหญ่:

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

0

เวอร์ชันของฉัน:

class String
    def upcase_first
        return self if empty?
        dup.tap {|s| s[0] = s[0].upcase }
    end
    def upcase_first!
        replace upcase_first
    end
end

['NASA title', 'MHz', 'sputnik'].map &:upcase_first  #=> ["NASA title", "MHz", "Sputnik"]

ตรวจสอบด้วย:
https://www.rubydoc.info/gems/activesupport/5.0.0.1/String%3Aupcase_first
https://www.rubydoc.info/gems/activesupport/5.0.0.1/ActiveSupport/Inflector#upcase_first-instance_method

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.