ใช้ประโยชน์จากอักขระตัวแรกของสตริงเท่านั้นและปล่อยให้คนอื่นอยู่คนเดียว? (ราง)


103

ฉันกำลังพยายามทำให้ Rails ใช้ประโยชน์จากอักขระตัวแรกของสตริงและปล่อยให้คนอื่น ๆ เป็นแบบที่เป็นอยู่ ฉันกำลังประสบปัญหาที่ทำให้ "ฉันมาจากนิวยอร์ก" กลายเป็น "ฉันมาจากนิวยอร์ก"

ฉันจะใช้วิธีใดในการเลือกอักขระตัวแรก

ขอบคุณ

แก้ไข:ฉันพยายามใช้สิ่งที่ macek แนะนำ แต่ฉันได้รับข้อผิดพลาด"วิธีการที่ไม่ได้กำหนดเป็นตัวพิมพ์ใหญ่" รหัสทำงานได้ดีโดยไม่มีบรรทัดตัวพิมพ์ใหญ่ ขอบคุณสำหรับความช่วยเหลือ!

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

แก้ไข 2:ใช้งานได้ ขอบคุณสำหรับความช่วยเหลือ!

แก้ไข 3:เดี๋ยวก่อนไม่ฉันไม่ได้ ... นี่คือสิ่งที่ฉันมีในแบบจำลองรายการของฉัน

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

แก้ไข 4:พยายามแก้ไขของ macek แล้ว แต่ยังได้รับข้อผิดพลาดวิธีการที่ไม่ได้กำหนดเป็นตัวพิมพ์ใหญ่ฉันจะทำอะไรผิด?

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

แก้ไข 5:นี่มันแปลก ฉันสามารถกำจัดข้อผิดพลาดของวิธีการที่ไม่ได้กำหนดได้โดยใช้บรรทัดด้านล่าง ปัญหาคือดูเหมือนว่าจะแทนที่ตัวอักษรตัวแรกด้วยตัวเลข ตัวอย่างเช่นแทนที่จะใช้ตัวพิมพ์ใหญ่yในYouมันจะเปลี่ยนyให้เป็น 121

self.title[0] = title[0].to_s.capitalize

ขึ้นอยู่กับคุณจะต้องเริ่มต้นด้วยสายEDIT 3 2 self.title = นอกจากนี้ในทั้ง 3 บรรทัดคุณต้องself.titleอยู่ทางซ้ายของ=(เครื่องหมายเท่ากับ) เท่านั้น ในสถานที่อื่น ๆ คุณสามารถtitleใช้ได้ ดูตัวอย่างการแก้ไขคำตอบของฉัน
maček

2
ปัญหาใน Edit4 คือคุณมีเพียงอักขระ - ไม่ใช่สตริงอีกต่อไปดังนั้นจึงไม่รู้จักฟังก์ชันสตริง "ตัวพิมพ์ใหญ่"
Taryn East

ปัญหาในการแก้ไข 5 คือ title [0] เป็น fixnum ดังนั้นการเรียก title [0] .to_s จะให้หมายเลขอักขระ (เช่น 121 เป็นสตริง: "121") คุณสามารถทำ self.title [0] = title.first.capitalize ได้หากต้องการ!
นิค

ฉันเพิ่ม #upcase_first_case และได้ขอดึง: github.com/rails/rails/pull/15319 อย่าลังเลที่จะเพิ่มความคิดเห็นของคุณที่นั่น
Aldo 'xoen' Giambelluca

คำตอบ:


93

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

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

อัปเดต:

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..."

เดี๋ยวยังใช้ไม่ได้ สัญญาณเตือนผิดพลาด: / ฉันคิดว่าฉันใช้ผิด
Daniel O'Connor

1
Daniel - โดยทั่วไปแล้วการ "ยอมรับ" คำตอบที่ช่วยแก้ปัญหาของคุณได้นั้นเป็นรูปแบบที่ดี คุณสามารถทำได้โดยคลิก "ขีด" ทางด้านซ้ายของคำตอบ :)
Taryn East

1
ฉันเข้าใจคำถามผิดไม่เช่นนั้นฉันอยากจะให้คุณเป็น 1 ฉันกำลังมองหา .titleize แทนที่จะเป็น. Capitalize ขอบคุณ Taryn!
Eric Wanchic

OOC - เหตุใดจึงหยุดไม่ให้โหวตเพิ่ม ฉันตอบคำถามของผู้โพสต์ต้นฉบับถูกต้องหรือไม่? ถ้าคุณคิดอย่างนั้น - โหวตให้คะแนน ไม่จำเป็นต้องขึ้นอยู่กับสิ่งอื่นใด ... :)
Taryn East

2
ดังนั้นนี่คือ: s[0].capitalize + s[1..-1] if s.present?
Alex Escalante

128

สิ่งนี้ควรทำ:

title = "test test"     
title[0] = title[0].capitalize
puts title # "Test test"

40
หรือกระชับกว่านั้นtitle[0] = title[0].capitalize
Jon Garvin

นี่เป็นวิธีการแก้ปัญหาที่สง่างามมาก
Karew

1
@JonGarvin title [0] .capitalize ใช้ไม่ได้ (อย่างน้อยกับ Ruby 1.8.7) เนื่องจาก title [0] ส่งคืน Fixnum และใช้ตัวพิมพ์ใหญ่คาดว่าจะเป็นสตริง .. ดังนั้นฉันคิดว่า title.first.capitalize เป็นวิธีที่จะ ไป.
นิค

2
อัปยศที่คุณทำไม่ได้title.first.capitalize!
Adam Waite

1
capitalizeแปลงตัวอักษรทั้งหมดหลังจากตัวอักษรตัวแรกเป็นตัวพิมพ์เล็กดังนั้นจึงไม่สามารถใช้ได้กับสตริงที่แสดงในคำถาม ("ฉันมาจากนิวยอร์ก")
Mark Schneider

57

คุณสามารถใช้ความเป็นมนุษย์ หากคุณไม่ต้องการขีดล่างหรือตัวพิมพ์ใหญ่อื่น ๆ ในบรรทัดข้อความของคุณ

อินพุต:

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

เอาท์พุต:

"I'm from new york..."

7
OP ต้องการหลีกเลี่ยง 'นิวยอร์ก' โดยเฉพาะ
phatmann

อืมเร็วไปหน่อยกับคำตอบของฉัน
Bartuzz

17
@Bartuzz แม้ว่านี่จะไม่ใช่สิ่งที่ OP ต้องการ แต่นี่คือสิ่งที่ฉันกำลังมองหา ขอบคุณ!
Yetti

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

ได้รับการเตือนhumanizeคือ Rails ซึ่งเป็นเมธอด ActiveSupport ทับทิมธรรมดาไม่สามารถทำเช่นนั้นได้
Penguin

52
str = "this is a Test"
str.sub(/^./, &:upcase)
# => "This is a Test"

1
กระชับและสง่างาม ฉันเชื่อว่านี่น่าจะเป็นคำตอบอันดับต้น ๆ
คริส

ฉันเห็นด้วย. ฉันคิดว่านี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Garry Pettet

หนึ่งมุมแหลมคือตั้งแต่^หมายถึงจุดเริ่มต้นของเส้นจะกลายเป็น"\nfoo" "\nFoo"นั่นอาจจะดีสำหรับกรณีการใช้งานส่วนใหญ่ เนื่องจากเป็น a subและไม่ใช่ a gsubมันจะยังคงเป็นตัวอักษรเพียงตัวเดียวแม้ว่าจะมีสตริงหลายบรรทัดก็ตาม
Henrik N

สามารถรับข้อ จำกัด ข้างต้นได้โดยใช้str.sub(/\S/, &:upcase)ซึ่งจะค้นหาอักขระที่ไม่ใช่ช่องว่างตัวแรกและยกตัวพิมพ์ใหญ่ขึ้น
Anthony Panozzo

39

สำหรับRails 5.0.0.beta4คุณสามารถใช้String#upcase_firstวิธีการใหม่หรือActiveSupport::Inflector#upcase_firstจะทำก็ได้ ตรวจสอบโพสต์บล็อกนี้สำหรับข้อมูลเพิ่มเติม


นั่นเป็นข่าวดี! ตอนนี้กำลังคิดว่าเราจะทำอะไรได้บ้างและบางทีการทำ polyfill สำหรับ Rails 4 ก็น่าจะดี
hakunin

โปรดทราบว่า upcase_first และไม่จัดการสำเนียง / ตัวอักษรพิเศษแม้จะมี mb_chars ก็ตาม
user3033467

14

โซลูชันเชิงวัตถุ:

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

จากนั้นคุณสามารถทำได้:

"i'm from New York".capitalize_first_char

อย่างน้อยก็มีใครบางคนเขียนคำตอบที่สวยงามพร้อมการขยายStringชั้นเรียน
Dmitriy

@Dmitriy ทำไมลิงถึงปะชั้นสตริงสวยหรู?
Gerard Simpson


6

แก้ไข 2

ดูเหมือนฉันจะทำซ้ำปัญหาของคุณไม่ได้ ไปข้างหน้าและเรียกใช้สคริปต์ Ruby ดั้งเดิมนี้ สร้างผลลัพธ์ที่แน่นอนที่คุณต้องการและ Rails รองรับวิธีการเหล่านี้ทั้งหมด อินพุตประเภทใดที่คุณประสบปัญหา

#!/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

เอาท์พุท

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..."

แก้ไข

จากการแก้ไขของคุณคุณสามารถลองทำสิ่งนี้ได้

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

ต้นฉบับ

นี้จะทำเคล็ดลับ

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

เมื่อพยายามใช้String#capitalizeกับสตริงทั้งหมดคุณจะเห็นI'm from new yorkเพราะวิธีการ:

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

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

+1 ทำให้ฉันไม่คิดว่าจะได้ผลจนกว่าฉันจะลองใช้บนพีซีของฉัน :)
Jeriko

สวัสดีขอบคุณสำหรับความช่วยเหลือ ฉันทำอะไรผิด? ฉันได้แก้ไขคำถามเดิมเพื่อรวมรหัสของฉัน
Daniel O'Connor

ฉันใช้คำแนะนำของ Taryn และได้ผล ขอบคุณสำหรับความช่วยเหลือ!
Daniel O'Connor

สวัสดี stackoverflow แจ้งว่าคุณได้ทำการแก้ไข แต่ฉันไม่เห็นอะไรที่แตกต่าง?
Daniel O'Connor


4

คำตอบเหล่านี้ส่วนใหญ่แก้ไขสตริงในสถานที่เมื่อคุณกำลังจัดรูปแบบสำหรับเอาต์พุตมุมมองคุณอาจไม่ต้องการเปลี่ยนสตริงที่อยู่ภายใต้เพื่อให้คุณสามารถใช้tapหลังจาก a dupเพื่อรับสำเนาที่แก้ไข

'test'.dup.tap { |string| string[0] = string[0].upcase }

3

ถ้า OP ต้องการทำการแพทช์ลิงบนวัตถุ String เท่านั้นก็สามารถใช้ได้

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

ตอนนี้ใช้มัน:

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


2

gsub ที่ไม่มีใครกล่าวถึงซึ่งช่วยให้คุณทำสิ่งนี้ได้อย่างรัดกุม

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

ตัวอย่าง:

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


1

โปรดทราบว่าหากคุณต้องการจัดการกับอักขระแบบหลายไบต์เช่นหากคุณต้องทำให้ไซต์ของคุณเป็นสากลการs[0] = ...แก้ปัญหาจะไม่เพียงพอ คำถาม Stack Overflow นี้แนะนำให้ใช้อัญมณี Unicode-util

Ruby 1.9: ฉันจะยกสตริงหลายไบต์ขึ้น - ลงอย่างถูกต้องได้อย่างไร

แก้ไข

จริงๆแล้ววิธีที่ง่ายกว่าอย่างน้อยที่สุดในการหลีกเลี่ยงการเข้ารหัสสตริงแปลก ๆ คือใช้String # mb_chars :

s = s.mb_chars
s[0] = s.first.upcase
s.to_s

-1

สิ่งที่เกี่ยวกับวิธีการจำแนกในสตริง?

'somESTRIng'.classify

เอาต์พุต:

#rails => 'SomESTRIng'

2
มันทำหลายอย่างเพิ่มเติมเช่นการแยกคำ "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

น่าจะเป็นแบบนั้น. ฉันยังใหม่กับทับทิมและคำตอบอื่น ๆ ไม่ได้ทำตามที่ OP ถามจริงๆฉันจึงทำให้มันได้ผล: D แก้ไขฉันถ้าฉันผิด แต่ AFAIK แก้ไขสตริงโดยเปลี่ยนสตริง [i] ไม่ได้ ทำงานได้หลายภาษา?
Jeriko

3
นี่คือคำถามเฉพาะของ Ruby ไม่สำคัญว่าstring[i]จะใช้ไม่ได้ในภาษาอื่น โปรดช่วยให้ StackOverflow ปราศจากความยุ่งเหยิงจากคำตอบที่ถูกแฮ็กประเภทนี้ เราไม่สามารถพูด RTFM แต่แม้กระทั่งอย่างรวดเร็วทันทีที่Stringเอกสารจะได้ช่วยหลีกเลี่ยงคำตอบเช่นนี้ ...
MACEK
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.