Використовуйте лише перший символ рядка, а інших залишайте в спокої? (Рейки)


102

Я намагаюся змусити Рейлів використовувати великі літери першого рядка, а всіх інших залишити такими, якими вони є. У мене виникає проблема, коли "я з Нью-Йорка" перетворюється на "Я з Нью-Йорка".

Який метод я б використав для вибору першого символу?

Дякую

EDIT: Я намагався реалізувати те, що запропонував 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: Діє. Дякую за допомогу!

EDIT 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

EDIT 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

EDIT 5: Це дивно. Я можу позбутися від невизначеної помилки методу за допомогою рядка нижче. Проблема полягає в тому, що начебто перша літера замінюється цифрою. Наприклад, замість того, щоб використовувати величину y в Тобі , вона перетворює y на 121

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

Виходячи з цього EDIT 3, потрібно починати рядок 2 self.title = . Крім того, для всіх 3 рядків вам потрібно лише self.titleзліва від =знака (рівний знак). В інших місцях ви можете просто користуватися title. Для прикладу дивіться редагування моєї відповіді.
maček

2
Проблема в Edit4 полягає в тому, що у вас є лише символ - це вже не рядок - тому він не розпізнає рядкову функцію "з великої літери".
Тарін Схід

Проблема редагування 5 полягає в тому, що заголовок [0] є фіксованим номером, тому виклик заголовка [0] .to_s просто дасть вам номер символу (тобто 121 як рядок: "121"). Ви можете зробити self.title [0] = title.first.capitalize, якщо хочете!
Нік

Я додав #upcase_first_case і зробив запит на потяг: github.com/rails/rails/pull/15319 . Не соромтеся додавати туди свій відгук.
Aldo 'xoen' Giambelluca

Відповіді:


93

Заголовок з великої літери зазначає великі літери кожного слова. Цей рядок відчуває себе здоровим, але гарантує, що єдина змінена літера - перша.

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

Зачекайте, все ще не працює. Помилкова тривога: / Я думаю, що я просто неправильно її реалізую.
Даніель О'Коннор

1
Даніель - це взагалі гарна форма "прийняти" відповідь, яка вирішила вашу проблему. Ви можете зробити це, натиснувши "галочку" зліва від відповіді. :)
Taryn East

1
Я неправильно зрозумів питання, інакше я хотів дати тобі 1. Я шукав .titleize замість .capitalize. Все одно дякую, Тарин!
Ерік Ванчич

OOC - Чому це не заважає вам дати нагороду? Чи правильно я відповів на питання оригінального плаката? Якщо ви так вважаєте - тоді виправдайте. Це не повинно залежати ні від чого іншого :) :)
Taryn East

2
Отже, ось так: s[0].capitalize + s[1..-1] if s.present?
Alex Escalante

126

Це слід зробити:

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

40
Або більш стисло,title[0] = title[0].capitalize
Джон Гарвін

Це дуже елегантне рішення.
Karew

1
@JonGarvin title [0] .capitalize не працює (принаймні, з Ruby 1.8.7), оскільки title [0] повертає Fixnum, а з великої літери очікує рядок .. тому я думаю, що title.first.capitalize - це шлях до йти.
Нік

2
сором, що не можетеtitle.first.capitalize!
Адам Уайт

1
capitalizeперетворює всі літери після першої літери в малі, тому він не працює для рядка, представленого у запитанні ("я з Нью-Йорка").
Марк Шнайдер

57

Можна використовувати гуманізацію. Якщо вам не потрібні підкреслення або інші великі літери у текстових рядках.

Вхід:

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

Вихід:

"I'm from new york..."

7
ОП спеціально хотіла уникнути "Нью-
Йорка

Хм, справді, занадто швидко з моєю відповіддю.
Бартуз

17
@Bartuzz Хоча це не те, чого хотів ОП, саме це я шукав. Дякую!
Йетті

Однак нью-йорк був би неграматичним як власне іменник і повинен використовувати великі літери.
Шейне

Будьте попереджені, humanizeчи саме метод Rails - саме ActiveSupport. Звичайний рубін не може цього зробити.
Пінгвін

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

1
Лаконічний і елегантний. Я вважаю, що це має бути головна відповідь.
Кріс

Я згоден. Я думаю, це має бути прийнятою відповіддю.
Гаррі Петтет

Одна примха полягає в тому, що, оскільки ^означає початок рядка, "\nfoo"стає "\nFoo". Це, мабуть, добре для більшості випадків використання. Оскільки це "а", subа не "" gsub, воно буде мати лише одну літеру, навіть з багаторядковими рядками.
Генрік N

Ви можете отримати обмеження вище, скориставшись str.sub(/\S/, &:upcase), який знайде перший символ, який не є пробілом, та покращить його.
Ентоні

39

Станом на Rails 5.0.0.beta4 ви можете використовувати новий String#upcase_firstметод або ActiveSupport::Inflector#upcase_firstзробити це. Перегляньте це повідомлення в блозі для отримання додаткової інформації.


Це чудова новина! Я думав, що ми можемо зробити зараз, і, можливо, поліфіл для Rails 4 буде непоганий.
хакунін

Зауважте, що 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, чому мавпа виправляє клас струн?
Джерард Сімпсон


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

Привіт, дякую за допомогу. Що я роблю неправильно? Я відредагував оригінальне запитання, щоб включити свій код.
Даніель О'Коннор

Я скористався пропозицією Таріна і спрацював. Дякую за допомогу, хоча!
Даніель О'Коннор

Привіт, stackoverflow каже, що ви внесли зміни, але я не бачу нічого іншого?
Даніель О'Коннор


4

Більшість із цих відповідей редагують рядок на місці, коли ви просто форматуєте для виводу перегляду, ви, можливо, не захочете змінювати базовий рядок, щоб ви могли використовувати tapпісля, 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

Ще коротша версія може бути:

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

2

Ніхто не згадує gsub, що дозволяє це робити стисло.

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

Приклад:

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


1

Зауважте, що якщо вам потрібно мати багатобайтові символи, тобто якщо вам доведеться інтернаціоналізувати свій сайт, s[0] = ...рішення не буде адекватним. Це запитання щодо переповнення стека пропонує використовувати дорогоцінний камінь unicode-util

Ruby 1.9: як я можу правильно змінити і зменшити багатобайтові рядки?

EDIT

Насправді, простішим способом уникнути дивних кодування рядків є просто використання String # mb_chars :

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

0

А як щодо методу класифікації на рядку?

'somESTRIng'.classify

вихід:

#rails => 'SomESTRIng'

1
Це робить багато додаткових речей, як-то сингулярні слова. "hello worlds".classify # => "Hello world"
Павло Правосуд

-3
string = "i'm from New York"
string.split(/\s+/).each{ |word,i| word.capitalize! unless i > 0 }.join(' ')
# => I'm from New York

Здається, так. Я новачок у рубіні, а інші відповіді насправді не виконували те, про що попросив ОП, тому я змусив його працювати: D Виправте мене, якщо я помиляюся, але AFAIK змінив рядок, змінивши рядок [i] не працювати на багатьох мовах?
Єрико

3
це специфічне для Рубі питання. Не має значення, якщо string[i]він не працює іншими мовами. Будь ласка, допоможіть зберегти StackOverflow безладно від таких видів злому відповідей. Ми не можемо сказати, що RTFM, але навіть швидкий погляд на Stringдокументи допоможе уникнути такої відповіді ...
maček
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.