ruby 大写不适用于标题的第一个单词

ruby capitalize doesnt work for the first word of the title

下面的代码是除了'littleWords'和标题的第一个单词之外的所有单词都大写。 (即使属于littleWords,首字也要大写。)

 def titleize (word)
    littleWords = ["and", "the", "over", "or"]

    words = Array.new
    words = word.split(" ")
    titleWords = Array.new

    words.each {|word, index| 
        if index == 0
            word = word.capitalize
        else
            unless littleWords.include?(word)
                word = word.capitalize
            end
        end
        titleWords << word
    }
    return titleWords.join(" ")
end 

测试代码如下

it "does capitalize 'little words' at the start of a title" do
    expect(titleize("the bridge over the river chao praya")).to eq("The Bridge over         the River chao praya")
  end

但它始终将第一个 'the' 大写为 'the' 而不是 'The'。我想知道我的代码的哪一部分是错误的。帮帮我...TT

您应该使用 each_with_index 而不是 each 来获得 index

正如您从 the documentation of Array#each 中看到的那样,它只产生一个块参数:

each { |item| block } → ary
#      ↑↑↑↑↑↑

但是,您的块有两个参数:

words.each {|word, index| 
#           ↑↑↑↑↑↑↑↑↑↑↑↑↑

由于 each 只为块生成一个参数,第二个参数将始终是 nil。 (除非元素恰好是 Array,然后 word 将绑定到数组的第一个元素,而 index 将绑定到第二个元素。)并且由于 index 是总是 nil,它永远不会等于 0,因此永远不会进入条件的第一个分支。

但是,还有另一种迭代方法,它实际上为块生成两个参数,即元素及其索引,称为 Enumerable#each_with_index:

words.each_with_index {|word, index| 
#         ↑↑↑↑↑↑↑↑↑↑↑

这就是使代码正常工作所需的全部更改。

这里,另一种不使用 eacheach_with_index 的方式。

def titleize (word)
    littleWords = ["and", "the", "over", "or"]
    words = word.split(" ")
    words[0].capitalize + " " + words[1..-1].map do |w|
        littleWords.include?(w) ? w : w.capitalize
    end.join(" ")
end

您可以将 String#gsub 与正则表达式和块一起使用。

def titlesize(str, little_words)
  str.gsub(/[[:alpha:]]+/) { |w| little_words.include?(w) &
   (Regexp.last_match.begin(0) > 0) ? w : w.capitalize }
end

little_words等于数组["and","the","over","of"],

titlesize "the days of wine and roses", little_words
  #=> "The Days of Wine and Roses"

参见Regexp::last_match and MatchData#beginRegexp.last_match可以用全局变量$~代替。