Как сделать первую букву строки в Ruby заглавной

134

upcaseМетод заглавной всю строку, но мне нужно , чтобы извлечь выгоду только первую букву.

Кроме того, мне нужно поддерживать несколько популярных языков, например немецкий и русский.

Как мне это сделать?

AntonAL
источник
4
Имейте в виду, что в некоторых языках существуют разные представления о том, какая первая буква должна быть заглавной. На ирландском языке вы делаете что-то вроде «i mBaile Átha Cliath» («в Дублине») - строчная буква «м», заглавная буква «Б». (См. En.wikipedia.org/wiki/Consonant_mutation#Celtic_languages, если вам интересно, почему ирландцы поступили так и почему это имеет смысл.)
Джеймс Мур,
3
Также имейте в виду, что #capitalize уберет все буквы, которые не являются первыми буквами ... что не всегда то, что вам нужно. ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

Ответы:

260

Это зависит от того, какую версию Ruby вы используете:

Ruby 2.4 и выше:

Это просто работает, поскольку Ruby v2.4.0 поддерживает отображение регистра Unicode:

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

Ruby 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

работает без ошибок, но также смотрите раздел «Ruby 2.3 и ниже», чтобы узнать о заглавных буквах.

Альберто Сантини
источник
19
Обратите внимание, что, по-видимому, "my API is great".capitalizeбудет My api is greatпроисходить нежелательное поведение. Таким образом, этот ответ на самом деле не отвечает на вопрос, поскольку он хочет, чтобы только ПЕРВАЯ буква была переведена в верхний регистр, а другие не были затронуты.
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
boulder_ruby
источник
1
Проголосуйте за чистое решение на Ruby.
Лень запускать
19

К сожалению, машина не может правильно использовать верхний / нижний регистр / заглавные буквы. Ему требуется слишком много контекстной информации, чтобы компьютер мог ее понять.

Вот почему Stringкласс Ruby поддерживает только заглавные буквы для символов ASCII, потому что там он хотя бы несколько четко определен.

Что я имею в виду под «контекстной информацией»?

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

Но Ruby не знает языка, он знает только кодировку. Поэтому невозможно правильно использовать заглавные буквы в строке с помощью встроенных функций Ruby.

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

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

Йорг Миттаг
источник
4
Извините, но ваша аргументация не выдерживает критики. Неверно, что Ruby решает вообще не отвечать, Ruby всегда дает ответ, который часто бывает неправильным - например, «мария» .upcase никогда не должен возвращать «мария», что неверно ни в каком контексте. И ваше отступление о необходимости ИИ вообще не актуально - нет ничего, что мешало бы сохранить массив в верхнем регистре, например ['I', 'İ'] для 'i'. Upcase, и позволить вызывающему абоненту решить, какой регистр уместен. в данной ситуации. В настоящее время Ruby не работает с преобразованием верхнего и нижнего регистра, и все.
michau
2
-1 потому что есть столица Eszett . Использование некоторой не полностью формализованной области не может служить доказательством того, что решение возможно только с ИИ.
Майк,
15

Ну, просто чтобы мы знали, как использовать только первую букву с заглавной буквы и оставить остальные в покое, потому что иногда это то, что желательно:

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

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

Вызов capitalizeприведет к ["Nasa", "Mhz", "Sputnik"].

Huliax
источник
Спасибо, именно то, что я искал, полезно для преобразования заголовков в «регистр предложений»
Good Lux
2
word[0] = word[0].upcase
Дэвид
@David. НЕТ! Это изменяет значения слов в массиве, для которого вызывается #collect. Это плохой побочный эффект.
Huliax
Я показал более простой способ сделать первую букву слова заглавной, заменив внутренние 3 строки этого решения, что я прояснил с помощью wordпеременной. Конечно, если у вас есть еще слова, просто назовите их все! ;)words.map{|word| word[0] = word[0].upcase}
Дэвид
@David. Ваш код составляет #capitalize!и нет #capitalize. Последний возвращает новую строку, а первый модифицирует получателя метода (в данном случае получатель является, wordа метод есть #[]). Если вы использовали свой код внутри блока #collect, то в итоге вы получили бы два разных массива с одинаковыми объектами String в каждом из них (и строки были бы изменены). Обычно вы этого не делаете. Даже если вы знаете об этом, другие читатели должны это понимать.
Huliax
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: New upcase_first Method " для получения дополнительной информации.

user1519240
источник
3

Использование capitalize. Из документации String :

Возвращает копию str с первым символом, преобразованным в верхний регистр, а остаток в нижний регистр.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"
jhwist
источник
Используйте восклицательный знак только в том случае, если вы хотите изменить исходную строку.
Magnar
doh Спасибо, исправил мою ошибку.
jhwist
5
-1. ОП явно упоминает немецкий и русский текст, что подразумевает символы, отличные от 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 (который был выпущен в 2016 году).
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"
phlegx
источник
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"
nisetama
источник