Ruby创建标题案例方法,无法处理像McDuff或McComb这样的单词

Pad*_*wan 0 ruby

该方法应该采用书籍的名称,并以适当的标题案例返回.所有我的规范pass()处理非字母字符,处理大写和混合大小写)除了最后一个返回特殊单词,如McDuff或McComb与大写第三个字母.有谁看到我做错了什么?并且,有没有办法简化这一点,使用手头的工具,而不是一些更高级别的快捷方式?

class String
  define_method(:title_case) do
    sentence_array = self.downcase.split
    no_caps = ["a", "an", "the", "at", "by", "and", "as", "but", "or", "for", "in", "nor", "on", "at", "up", "to", "on", "of", "from", "by"]

    sentence_array.each do |word|
      if no_caps.include?(word)
        word
      else
        word.capitalize!
      end
      sentence_array.first.capitalize!

      #  Manage special words
      if (word.include?("mc"))
        letter_array = word.split!("")    # word with mc changed to an array of letters
          if (letter_array[0] == "m") && (letter_array[1] == "c")  # 1st & 2nd letters
            letter_array[2].capitalize!
            word = letter_array.join
          end
      end  
    end
    sentence_array.join(" ")
  end
end
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 5

您的"Mc"代码有几个问题:

if (word.include?("mc"))
Run Code Online (Sandbox Code Playgroud)

这将永远返回false,因为您已经大写word.它一定要是:

if word.include?('Mc')
Run Code Online (Sandbox Code Playgroud)

这条线也不起作用:

letter_array = word.split!("")
Run Code Online (Sandbox Code Playgroud)

因为没有split!方法,只是split.但是根本没有理由使用字符数组.String#[]允许您访问字符串的字符(或子字符串),因此下一行变为:

if (word[0] == 'M') && (word[1] == 'c')
Run Code Online (Sandbox Code Playgroud)

要不就:

if word[0, 2] == 'Mc'
Run Code Online (Sandbox Code Playgroud)

甚至更好地使用start_with?:

if word.start_with?('Mc')
Run Code Online (Sandbox Code Playgroud)

事实上,我们可以if用这个替换第一个.

下一行有点棘手:

letter_array[2].capitalize!
Run Code Online (Sandbox Code Playgroud)

使用String#[]它成为:

word[2].capitalize!
Run Code Online (Sandbox Code Playgroud)

但不幸的是,两者都没有按预期工作.这是因为[]返回一个新对象,因此bang方法不会更改原始对象.相反,你必须调用元素赋值方法[]=:

word[2] = word[2].upcase
Run Code Online (Sandbox Code Playgroud)

一切都放在一起:

if word.start_with?('Mc')
  word[2] = word[2].upcase
end
Run Code Online (Sandbox Code Playgroud)

或者在一行中:

word[2] = word[2].upcase if word.start_with?('Mc')
Run Code Online (Sandbox Code Playgroud)

  • 我有几点要补充Stefan的优秀答案.1.`no no_caps.include?(word); 字; ...``if`语句的一部分没有效果.当`word`是``和``时,例如,`no_caps.include?("和")`是'true`,所以返回``和``,但它不被变量捕获,所以它也可能被射入外太空.2.由于`sentence_array.first.capitalize!`在`end`之前,因此对于`sentence_array`的每个元素执行一次.最好写:`sentence_array.each {| word | word.capitalize!除非no_caps.include?(word)}; sentence_array.first.capitalize!`. (2认同)