Ruby 将字符串转换为正确的标题大小写
我有以下练习: 编写一个用字符串初始化的Ruby 将字符串转换为正确的标题大小写,ruby,string,title-case,Ruby,String,Title Case,我有以下练习: 编写一个用字符串初始化的标题类 它有一个方法--fix--它应该返回字符串的标题大小写版本: Title.new(“书名”).fix= 书名 您需要使用条件逻辑--if和else语句来实现此功能。 确保仔细阅读测试规范,以便理解要实现的条件逻辑 您将要使用的一些方法: String#downcase String#大写 Array#include? 此外,这是Rspec,我应该包括: describe "Title" do describe "fix" do it "capita
标题类
它有一个方法--fix
--它应该返回字符串的标题大小写版本:
Title.new(“书名”).fix
=
书名
您需要使用条件逻辑--if
和else
语句来实现此功能。
确保仔细阅读测试规范,以便理解要实现的条件逻辑
您将要使用的一些方法:
String#downcase
String#大写
Array#include?
此外,这是Rspec,我应该包括:
describe "Title" do
describe "fix" do
it "capitalizes the first letter of each word" do
expect( Title.new("the great gatsby").fix ).to eq("The Great Gatsby")
end
it "works for words with mixed cases" do
expect( Title.new("liTTle reD Riding hOOD").fix ).to eq("Little Red Riding Hood")
end
it "downcases articles" do
expect( Title.new("The lord of the rings").fix ).to eq("The Lord of the Rings")
expect( Title.new("The sword And The stone").fix ).to eq("The Sword and the Stone")
expect( Title.new("the portrait of a lady").fix ).to eq("The Portrait of a Lady")
end
it "works for strings with all uppercase characters" do
expect( Title.new("THE SWORD AND THE STONE").fix ).to eq("The Sword and the Stone")
end
end
end
谢谢@simone,我采纳了您的建议:
class Title
attr_accessor :string
def initialize(string)
@string = string
end
IGNORE = %w(the of a and)
def fix
s = string.split(' ')
s.map do |word|
words = word.downcase
if IGNORE.include?(word)
words
else
words.capitalize
end
end
s.join(' ')
end
end
尽管我在运行代码时仍遇到错误:
expected: "The Great Gatsby"
got: "the great gatsby"
(compared using ==)
exercise_spec.rb:6:in `block (3 levels) in <top (required)>'
期待:《了不起的盖茨比》
得到:“伟大的盖茨比”
(使用==进行比较)
练习_规范rb:6:in‘分块(3层)in’
从初学者的角度来看,我看不出我做错了什么
最后的编辑:我只是想说谢谢大家之前为帮助我所付出的一切努力。我将展示我能够生成的最终工作代码:
class Title
attr_accessor :string
def initialize(string)
@string = string
end
def fix
word_list = %w{a of and the}
a = string.downcase.split(' ')
b = []
a.each_with_index do |word, index|
if index == 0 || !word_list.include?(word)
b << word.capitalize
else
b << word
end
end
b.join(' ')
end
end
课程名称
属性存取器:字符串
def初始化(字符串)
@字符串=字符串
结束
def修复
单词列表=%w{a of the}
a=string.downcase.split(“”)
b=[]
a、 每个带索引的单词,索引|
如果索引=0 | |!单词列表。包括?(单词)
这里有一个可能的解决办法
class Title
attr_accessor :string
IGNORES = %w( the of a and )
def initialize(string)
@string = string
end
def fix
tokens = string.split(' ')
tokens.map do |token|
token = token.downcase
if IGNORES.include?(token)
token
else
token.capitalize
end
end.join(" ")
end
end
Title.new("a title of a book").fix
你的出发点很好。以下是一些改进:
- 比较总是小写的。这将简化if条件
- 被忽略项的列表被放入一个数组中。这将简化if条件,因为您不需要为每个被忽略的字符串指定if(它们可能有数百个)
- 我使用地图来替换代币。使用带有枚举的块循环项是一种常见的Ruby模式
满足所有条件:
a、 是、of、the,且全部小写
将所有其他单词大写
所有第一个单词都大写
解释
string.downcase
调用一个操作,使正在使用的字符串全部小写
.split(/(\s)/)
采用小写字符串,并在空白处(空格、制表符、换行符等)将其拆分为一个数组,使每个单词成为数组的一个元素;括号中的\s
(分隔符)周围也会将其保留在返回的数组中,因此在重新加入时不会丢失该空格字符
.map.使用_index{124; x,i
迭代返回的数组,其中x
是值,i
是索引号;每次迭代返回一个新数组的元素;循环完成后,您将拥有一个新数组
(i==0 | | x.match(/^(?:a |是|和$/).nil?
如果它是数组中的第一个元素(索引为0),或者单词匹配a
,是
,是
,是
,或者和
,也就是说,匹配不是零
,那么x(它与忽略词匹配)因此只需返回单词/值,x
.join
使用我们的新数组,再次将所有单词组合成一个字符串
附加的
- 通常,正则表达式中括号内的内容被视为捕获组,这意味着如果内部的模式匹配,则在正则表达式操作完成后,一个特殊变量将保留该值。在某些情况下,例如
\s
我们希望捕获该值,因为我们重用了该值,在其他情况下,例如忽略字we需要匹配,但不需要捕获它们。要避免捕获匹配,您可以在捕获组的开头调整步调?:
,告诉正则表达式引擎不要保留该值。这有许多好处不属于此答案的范围
有两种方法可以解决此问题:
- 将字符串拆分为单词,可能修改每个单词并将单词重新连接在一起;或者
- 使用正则表达式
我会说一些关于后者的事情,但我相信你的练习涉及到前者——这是你所采取的方法——所以我将集中讨论这一点
将字符串拆分为单词
您可以使用
String#split(“”)
将字符串拆分为单词:
str = "a title of a\t book"
a = str.split(' ')
#=> ["a", "title", "of", "a", "book"]
这很好,即使有额外的空白,但通常会这样写:
str.split
#=> ["a", "title", "of", "a", "book"]
这两种方法都是相同的
str.split(/\s+/)
#=> ["a", "title", "of", "a", "book"]
请注意,我使用变量a
表示数组是返回的。有些人可能觉得这不够描述性,但我认为它比s
更好,这有点让人困惑。:-)
创建枚举数
接下来,发送方法Enumerable#each_with_index
以创建枚举器:
enum0 = a.each_with_index
# => #<Enumerator: ["a", "title", "of", "a", "book"]:each_with_index>
您使用了带有索引的每个单词,因为第一个单词(索引为0的单词)的处理方式与其他单词不同。这很好
到目前为止还不错,但此时您需要使用Enumerable#map
将enum0
的每个元素转换为适当的值。例如,第一个值,[“a”,0]
将转换为“a”,下一个值将转换为“Title”,第三个值将转换为“of”
因此,您需要将方法Enumerable#map
发送到enum0
:
enum1 = enum.map
#=> #<Enumerator: #<Enumerator: ["a", "title", "of", "a",
"book"]:each_with_index>:map>
enum1.to_a
#=> [["a", 0], ["title", 1], ["of", 2], ["a", 3], ["book", 4]]
最后,我们在每个单词之间加入一个空格:
b.join(' ')
=> "A Title of a Book"
查看计算细节
str = "a title of a book"
str.gsub(/(^\w+)|(\w+)/) do
$1 ? $1.capitalize :
articles.include?($2) ? $2 : $2.capitalize
end
#=> "A Title of a Book"
让我们回到b
的计算。enum1
的第一个元素被传递到块中并分配给块变量:
w, i = ["a", 0] #=> ["a", 0]
w #=> "a"
i #=> 0
因此,我们执行:
case 0
when 0 then "a".capitalize
else articles.include?("a") ? "a".downcase : "a".capitalize
end
它返回“a”。大写=>“a”
。类似地,当e的下一个元素
w, i = ["a", 0] #=> ["a", 0]
w #=> "a"
i #=> 0
case 0
when 0 then "a".capitalize
else articles.include?("a") ? "a".downcase : "a".capitalize
end
w, i = ["title", 1] #=> ["title", 1]
w #=> "title"
i #=> 1
case 1
when 0 then "title".capitalize
else articles.include?("title") ? "title".downcase : "title".capitalize
end
w, i = ["of", 2] #=> ["of", 2]
w #=> "of"
i #=> 2
case 2
when 0 then "of".capitalize
else articles.include?("of") ? "of".downcase : "of".capitalize
end
str.split.each_with_index.map do |w,i|
case i
when 0 then w.capitalize
else articles.include?(w) ? w.downcase : w.capitalize
end
end
#=> ["A", "Title", "of", "a", "Book"]
first_word, *remaining_words = str.split
first_word
#=> "a"
remaining_words
#=> ["title", "of", "a", "book"]
"#{first_word.capitalize} #{ remaining_words.map { |w|
articles.include?(w) ? w.downcase : w.capitalize }.join(' ') }"
#=> "A Title of a Book"
str = "a title of a book"
str.gsub(/(^\w+)|(\w+)/) do
$1 ? $1.capitalize :
articles.include?($2) ? $2 : $2.capitalize
end
#=> "A Title of a Book"
class Title
attr_accessor :str
def initialize(str)
@str = str
end
def fix
s = str.downcase.split(" ") #convert all the strings to downcase and it will be stored in an array
words_cap = []
ignore = %w( of a and the ) # List of words to be ignored
s.each do |item|
if ignore.include?(item) # check whether word in an array is one of the words in ignore list.If it is yes, don't capitalize.
words_cap << item
else
words_cap << item.capitalize
end
end
sentence = words_cap.join(" ") # convert an array of strings to sentence
new_sentence =sentence.slice(0,1).capitalize + sentence.slice(1..-1) #Capitalize first word of the sentence. Incase it is not capitalized while checking the ignore list.
end
end