我试图建立一种方法,你取每个单词的第一个字母,并将其大写。我把它写成
def titleize(name)
name.scan(/w+/) { |x| x.capitalize! }
end
就不能正常工作了。它不会大写和字母。我做了一些搜索,最终在这里找到了答案大写标题。它被写成
def titleize(name)
name.split(" ").each { |x| x.capitalize! }.join(" ")
end
为什么我的代码没有大写呢?如果我添加一个put语句并将其写成
def titleize(name)
name.scan(/w+/) { |x| puts x.capitalize! }
end
它会输出大写的"hi there",但是=>仍然只是"hi there",我错过了什么?
更正代码:
def titleize(name)
name.scan(/w+/).each { |x| x.capitalize! }.join(' ')
end
p titleize("ayan roy") #=>"Ayan Roy"
让我们看看为什么你的不工作:
def titleize(name)
name.scan(/w+/)
end
p titleize("ayan roy") #=>["ayan", "roy"]
现在您的行name.scan(/w+/) { |x| x.capitalize! }
, x
被传递为"ayan", "roy"
。现在看看下面的代码:
def titleize(name)
name.scan(/w+/) { |x| p x.capitalize! }
end
p titleize("ayan roy")
输出:"Ayan"
"Roy"
"ayan roy"
As String#scan
说:
scan(pattern) {|match,…| block}→str -如果给定block,scan将返回调用它的
receiver
。这两种形式都遍历str,匹配模式(可以是Regexp或String)。对于每个匹配,生成一个结果并将其添加到结果数组中或传递到块中。
scan
返回/产生新字符串,并且永远不会修改源字符串。也许你想要gsub
。
def titleize(name)
name.gsub(/w+/) {|x| x.capitalize }
end
或者最好使用title gem中更正确的实现
您的代码不起作用,因为#scan
返回新的String
对象,这些对象是Regexp的结果并将它们传递给块。因此,在你的方法中,你本质上获得了这些新对象,通过调用#capitalize!
对它们进行了变异,但之后从未在任何地方使用过它们。
你应该这样做:
def titleize(name)
name.scan(/w+/).each { |x| x.capitalize! }.join(' ')
end
但这对我来说似乎更容易读:
def titleize2(name)
name.split(' ').each { |w| w.capitalize! }.join(' ')
end
请注意,这些方法不会改变传递的原始参数。
无论您在块中做了什么,scan
的块形式都会返回原始字符串。(我认为你可以通过直接引用它来改变块中的原始字符串,但不建议改变你正在迭代的东西。)相反,做你的split
变体,但不是each
,而是collect
,然后是join
:
name.split(" ").collect { |x| x.capitalize }.join(" ")
这也适用于包含数字和标点符号的标题。