Як написати велику літеру в рядку в рядку в Рубі


134

upcaseМетод великої всю рядок, але мені потрібно , щоб отримати вигоду тільки першу букву.

Також мені потрібно підтримувати кілька популярних мов, як німецька та російська.

Як це зробити?


4
Будьте в курсі, що деякі мови мають різні уявлення про те, що таке перша літера, що використовується з великої літери. В ірландській мові ви робите такі речі, як "i mBaile Átha Cliath" ("у Дубліні") - нижній регістр 'm', верхній регістр 'B'. (Див. En.wikipedia.org/wiki/Consonant_mutation#Celtic_languages, якщо вам цікаво, чому ірландці це робитимуть і чому це має сенс.)
Джеймс Мур

3
А також пам’ятайте, що #capitalize зменшить всі літери, які не є першою літерою ... що не завжди є тим, що ви хочете. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Хуліакс

Відповіді:


260

Це залежить від того, яку версію Ruby ви використовуєте:

Ruby 2.4 і вище:

Це просто працює, оскільки Ruby v2.4.0 підтримує відображення випадків Unicode:

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

Рубін 2.3 і нижче:

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

Проблема в тому, що вона просто не робить те, що ви хочете, а виводить мариязамість цього Мария.

Якщо ви використовуєте Rails, то тут просте вирішення:

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

Інакше вам доведеться встановити самоцвіт Unicode і використовувати його так:

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

працює без помилок, але також перегляньте розділ «Рубін 2.3 і нижче» для реальної капіталізації.


19
Зауважте, що, мабуть "my API is great".capitalize, спричинить My api is greatнебажану поведінку. Тож ця відповідь насправді не відповідає на запитання, оскільки він хоче лише ПЕРШИЙ лист звернутий у верхній регістр, а інші - недоторкані.
Даніель АР Вернер

55

з великої літери першого слова рядка

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

з великої літери кожного слова

У рейках:

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

АБО

"kirk_douglas".titleize
=> "Kirk Douglas"    

У рубіні:

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

за межами рейок, але все ж хочеться використовувати метод титулування

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

1
Запропонуйте чистий розчин Ruby. Занадто ліниво правильно підпалити Рейки, і це зробило трюк :)
illbzo1

19

На жаль, неможливо належним чином збільшити / зменшити капіталізацію машини. Для того, щоб зрозуміти комп'ютер, йому потрібно занадто багато контекстної інформації.

Ось чому Stringклас Рубі підтримує лише використання великих літер для символів ASCII, оскільки там принаймні дещо чітко визначені.

Що я маю на увазі під "контекстною інформацією"?

Наприклад, щоб iправильно писати великі літери , потрібно знати, на якій мові знаходиться текст. Англійська мова, наприклад, має лише два is: Iвелика літера без крапки та мала iз крапкою. Але турецька має чотири iс: капітал Iбез крапки, капітал İз крапкою, малий ıбез крапки, малий iз крапкою. Так, англійською 'i'.upcase # => 'I'та турецькою мовами 'i'.upcase # => 'İ'. Іншими словами: оскільки 'i'.upcaseможна повернути два різні результати, залежно від мови, очевидно неможливо правильно написати великі літери на великому літері, не знаючи його мови.

Але Рубі не знає мови, вона знає лише кодування. Тому неможливо правильно використовувати великі літери з вбудованою функціональністю Ruby.

Стає все гірше: навіть з знаючи мови, іноді неможливо зробити капіталізацію правильно. Наприклад, в німецькому мовою , 'Maße'.upcase # => 'MASSE'( MASSE це множина від MASS сенс виміру ). Однак, 'Masse'.upcase # => 'MASSE'(маючи на увазі масу ). Отже, що таке 'MASSE'.capitalize? Іншими словами: правильне використання великих літер вимагає всебічного штучного інтелекту.

Таким чином, замість того , щоб іноді дати неправильну відповідь, Рубі вирішує іноді не дає відповіді на всі , тому не-ASCII символи просто ігноруються в downcase / Upcase / капіталізувати операції. (Що, звичайно, також читає неправильні результати, але принаймні це легко перевірити.)


4
Вибачте, але Ваша аргументація не перешкоджає. Неправда, що Рубі вирішує взагалі не давати відповіді, Рубі завжди дає відповідь, що часто є неправильним - наприклад, "марія" .покупка ніколи не повинна повертати "марію", що не вірно в жодному контексті. І ваші відступи щодо необхідності AI взагалі не актуальні - ніщо не перешкоджає завантаженню масиву масиву, скажіть ['I', 'İ'] для 'i'.upcase, і дасть можливість абоненту вирішити, яка величина капіталізації є релевантною у даній ситуації. Наразі обробка перетворення між великими та малими літерами Ruby порушена, і все.
michau

2
-1 тому, що є столиця Ессетт . Використання деякої не повністю формалізованої області не може слугувати доказом того, що рішення можливо лише з AI.
Майк

15

Ну, просто так ми знаємо, як використовувати великі літери лише першу букву, а решту залишати в спокої, бо іноді саме так хочеться:

['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
Девід

@David. НЕМАЄ! Це змінює значення слів у масиві, на який викликається #collect. Це поганий побічний ефект.
Хуліякс

Я показав простіший спосіб написання великої літери першої літери слова, замінивши внутрішні 3 рядки цього рішення, що я зрозумів, використовуючи wordзмінну. Звичайно, якщо у вас є більше слів, просто зателефонуйте їм на всі! ;)words.map{|word| word[0] = word[0].upcase}
Девід

@David. Ваш код становить #capitalize!і ні #capitalize. Останній повертає нову String, тоді як перша модифікує приймач методу (у цьому випадку приймачем є wordі метод є #[]). Якщо ви використовували свій код всередині блоку #collect, ви отримаєте два різних масиви з однаковими об'єктами String у кожному з них (і рядки були б змінені). Звичайно, це не те, що ти хочеш робити. Навіть якщо ви це знаєте, інші читачі повинні це розуміти.
Хуліакс

8

Рейки 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: Новий upcase_first метод " для отримання додаткової інформації.


3

Використовуйте capitalize. З документації String :

Повертає копію str з першим символом, перетвореним у верхній регістр, а решта в малі.

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

Використовуйте знак оклику лише в тому випадку, якщо ви хочете змінити початковий рядок.
Магнар

До, дякую, виправив мою помилку.
jhwist

5
-1. В ОП чітко згадується німецький та російський текст, що передбачає символи, що не належать до ASCII. String#upcase(а також String#downcase) визначені лише для символів ASCII.
Йорг W Міттаг

1
Використання Ruby 2.5.0 сьогодні і, String#upcaseздається, добре працює на символах, що не належать до ASCII. 2.5.0 :001 > "мария".upcase => "МАРИЯ"
Хуліакс

1
@Huliax Як вже згадувалося у прийнятій відповіді, це було лише після Ruby 2.4.0 (який вийшов у 2016 році).
нісетама

2

Можна використовувати mb_chars. Це стосується умлауте:

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"

0

Нижче - ще один спосіб написання великих літер у кожному рядку. \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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.