该upcase
方法将整个字符串大写,但是我只需要大写第一个字母。
另外,我需要支持几种流行的语言,例如德语和俄语。
我该怎么做?
['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
该upcase
方法将整个字符串大写,但是我只需要大写第一个字母。
另外,我需要支持几种流行的语言,例如德语和俄语。
我该怎么做?
['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Answers:
这取决于您使用的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 gem并像这样使用它:
require 'unicode'
Unicode::capitalize("мария") #=> Мария
Ruby 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及更低版本”部分以获取大写字母。
"my API is great".capitalize
会产生My api is great
可能是不希望的行为。所以这个答案并没有真正回答这个问题,因为他只希望将FIRST字母变成大写而其他字母保持不变。
将字符串的第一个单词的首字母大写
"kirk douglas".capitalize
#=> "Kirk douglas"
每个单词的首字母大写
在导轨中:
"kirk douglas".titleize
=> "Kirk Douglas"
要么
"kirk_douglas".titleize
=> "Kirk Douglas"
在红宝石中:
"kirk douglas".split(/ |\_|\-/).map(&:capitalize).join(" ")
#=> "Kirk Douglas"
在rails之外,但仍想使用titleize方法
require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize
不幸的是,机器不可能正确地进行大写/小写/大写。它需要太多的上下文信息,计算机无法理解。
这就是Ruby的String
类仅支持ASCII字符大写的原因,因为那里至少有一些明确的定义。
我所说的“上下文信息”是什么意思?
例如,要i
正确地大写,您需要知道文本使用的语言。例如,英语只有两个i
s:I
不带点的大写字母和带点的小字母i
。但是土耳其语有四个i
s:大写字母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 /资本运作忽略。(当然,这也会读取错误的结果,但至少很容易检查。)
好吧,如此我们知道如何仅将首字母大写,而将其余首字母留空,因为有时需要这样做:
['NASA', 'MHz', 'sputnik'].collect do |word|
letters = word.split('')
letters.first.upcase!
letters.join
end
=> ["NASA", "MHz", "Sputnik"]
呼叫capitalize
将导致["Nasa", "Mhz", "Sputnik"]
。
word[0] = word[0].upcase
word
变量明确了这一点。当然,如果您有更多的单词,只需在所有单词上调用它们即可!;)words.map{|word| word[0] = word[0].upcase}
#capitalize!
而不是#capitalize
。后者返回一个新的String,而前者则修改该方法的接收者(在这种情况下,接收者为word
,方法为#[]
)。如果在#collect块中使用了代码,则最终将得到两个不同的数组,每个数组中的String对象相同(并且Strings将被修改)。那不是您通常想要做的。即使您知道这一点,其他读者也应该理解这一点。
从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方法 ”以获取更多信息。
使用capitalize
。从字符串文档中:
返回str的副本,第一个字符转换为大写,其余字符转换为小写。
"hello".capitalize #=> "Hello"
"HELLO".capitalize #=> "Hello"
"123ABC".capitalize #=> "123abc"
String#upcase
(以及String#downcase
)仅针对ASCII字符定义。
String#upcase
似乎可以在非ASCII字符上正常工作。2.5.0 :001 > "мария".upcase => "МАРИЯ"
下面是将字符串中每个单词大写的另一种方法。\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:]]
匹配“标点,连接器”(Pc
)类别中的所有10个字符:
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"