当我输入"战争与和平"时,我想要"战争与和平"。这个想法是采用一个字符串并使其看起来像标题或电影标题一样。将字符串中的所有单词大写,除非单词等于或小于 3 且不在开头。
当我运行此代码时:
def titleize(string)
string.split(" ").take(1).join.capitalize
string.split(" ").map do |x|
x.capitalize! if x.length > 3
end.join(" ")
end
它只返回"和平"。
试试这个:
title = 'war and peace'
def titleize(input)
input.split(' ').map.with_index { |word, index|
index == 0 || word.length > 3 ? word.capitalize : word
}.join(' ')
end
titleize title
=> "War and Peace"
你只返回"和平"的原因是因为map
为自身的每个元素调用给定块一次。
创建一个包含块返回的值的新数组。
当你做x.capitalize! if x.length > 3
,你返回nil
如果length <= 3
"war" if "war".length > 3
# => nil
因此,要完成这项工作,您需要确保为传递给块的每个单词返回一些内容
。def titleize(string)
string.capitalize.split.map do |x|
x.length > 3 ? x.capitalize : x
end.join(" ")
end
puts titleize("war and peace") # => "War and Peace"
另外,请注意capitalize!
通过将第一个字符转换为大写,将其余字符转换为小写来修改 str。如果未进行任何更改,则返回 nil。
而capitalize
返回 str 的副本,其中第一个字符转换为大写,其余字符转换为小写。
所以x.capitalize!
也可以返回nil
"Peace".capitalize!
=> nil
无需将字符串转换为单词数组,将具有三个以上字符的单词大写,将它们重新连接成字符串并大写结果字符串的第一个字符。此外,这将剥夺多余的空间,这可能是不希望的。
相反,可以简单地将 String#gsub 与正则表达式一起使用来进行替换。
r = /
A # match the start of the string
p{Lower} # match a lowercase letter
| # or
(?<=[ ]) # match a space in a positive lookbehind
p{Lower} # match a lowercase letter
(?=p{Alpha}{3}) # match 3 letters in a positive lookahead
/x # free-spacing regex definition mode
str = "now is the time for something to happen."
str.gsub(r) { |c| c.upcase }
#=> "Now is the Time for Something to Happen."
正则表达式是按惯例编写的
/Ap{Lower}|(?<= )p{Lower}(?=p{Alpha}{3})/
我使用p{Lower}
而不是p{Alpha}
来避免不必要的大写。
请注意,在自由间距模式下,正后视中的空格包含在字符类 ((?<=[ ])
( 中。这是因为自由间距模式会剥离所有不受保护的空间。
我会将字符串拆分为一个字符串数组,如下所示:
string.split(' ')
然后,如果给定字符串的长度大于 3,则每个字母大写:
for i in string.length
if string[i].length > 3
string[i].capitalize
现在只需连接字符串:
string.join(' ')
end
尝试:
def titleize(string)
string.split.map.with_index {|x,i| if (i == 0 || x.length > 3) then x.capitalize else x end }.join(' ')
end
请注意,这不会修改传入的字符串,但您可以执行以下操作
foo = 'war and peace'
foo = titleize foo
puts foo
War and Peace