2015-01-20 27 views
2

我无法找到解决此问题的解决方案,我做了一项研究以找到问题并修复它们,但无法想出任何答案。在Ruby中修改数组项目(如果它包含特定单词)

我想要做的是将字符串转换为标题套用字符串

例如: “魔戒三部曲”>“的指环王”

(正如你所看到的,第一个单词总是大写,它不会,如果是无关紧要一篇文章,但如果字符串中有文章词语,应该用小写字母表示,如上例所示,并且大写其他任何不是的单词)。

这是规范(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 

这是我的尝试,我到目前为止有:

class Title 
    def initialize(string) 
    @string = string 
    end 

    def fix 
    @string.split.each_with_index do |element, index| 
     if index == 0 
     p element.capitalize! 
     elsif index == 1 
     if element.include?('Is') || element.include?('is') 
      p element.downcase! 
     end 
     end 
    end 
    end 
end 

a = Title.new("this Is The End").fix 
p a 

输出:

“This”

“是”

=> [ “这”, “是”, “该”, “结束”]


我试图这样做:

  1. 创建一个名为Title的类并用一个字符串初始化它。
  2. 创建一个名为修复方法,到目前为止,只为指数检查0 的@string.split与方法.each_with_index(循环 通过),并打印element.capitalize!(注意是“砰”,即 应该修改原始字符串,你可以看到它的输出上面 )
  3. 我的代码确实是检查索引1(第二个字)和 调用.include?('is'),看看第二个字的文章, 如果是(与if语句)element.downcase!被调用, 如果不是,我可以创建更多的索引检查(但我意识到 这里有些字符串可能由3个字组成,其他字符由5个, 其他由10等等组成,所以我的代码效率不高, 这是我无法解决的问题。

也许创建一个文章词汇列表并检查.include?方法,如果有一些单词的名单? (我试过这个,但.include?方法只接受一个不是数组变量的字符串,我尝试了join(' ')方法,但没有运气)。

非常感谢! 真的是

+0

你可以通过使用'case'语句或'Set'来匹配你想要的小写字母来清理它。 – tadman 2015-01-20 23:09:38

+0

我运行了你的代码,它返回了'[“This”,“is”,“The”,“End”]',这与你发布的内容不符。 – 2015-01-20 23:14:46

+0

谢谢@Jordan它现在是最新的。 – bntzio 2015-01-20 23:16:51

回答

1

我喜欢在我编写算法之前,将这些类型的问题分解成更小的逻辑块以帮助我理解。在这种情况下,您需要根据一些规则修改字符串的每个单词。

  1. 如果这是第一个词,请将其大写。
  2. 如果它不是一个特殊的词,请将其大写。
  3. 如果它是一个特殊的词,并且它不是第一个词,则将其置之不理。

有了这些规则,你可以编写你的逻辑遵循。

special_words = ['a', 'an', 'and', 'of', 'the'] 
fixed_words = [] 
@string.downcase.split.each_with_index do |word, index| 
    # If this isn't the first word, and it's special, use downcase 
    if index > 0 and special_words.include?(word) 
     fixed_words << word 
    # It's either the first word, or not special, so capitalize 
    else 
     fixed_words << word.capitalize 
    end 
end 
fixed_words.join(" ") 

你会注意到在调用split和each_with_index之前,我在字符串上使用了downcase。这样,所有的单词都会被归一化,并且可以轻松地对照special_words数组进行检查。

我还将这些转换后的单词存储在一个数组中,并最终将它们连接在一起。原因是,如果我尝试使用downcase!或大写!在拆分字符串上,我不修改原始标题字符串。

注:这个问题是阵营完整的堆栈当然工作,这就是为什么我使用的是简化的解决方案,而不是一个衬垫,模块,文件IO等

1

我会在与你的程序相同的文件夹中创建一个新文件(在我的示例中,该文件被称为“exclude.txt”,并将“and”全部放在一个新行上, ð做这样的事情:

class String 
    def capitalize_first_letter 
    self[0].upcase + self[1..-1] 
    end 
end 

class Title 
    def initialize(string) 
    @string = string 
    @exclude_words = File.readlines('exclude.txt').map(&:downcase).map(&:chomp) 
    end 

    def fix 
    @string.downcase.gsub(/\S+/) do |word| 
     @exclude_words.include?(word) ? word : word.capitalize 
    end.capitalize_first_letter 
    end 
end 

假设你exclude.txt文件中包含要保留downcase(矿中含有的,上一个,就是,和)的话,所有的测试都应该获得通过:

p Title.new("the great gatsby").fix #=> "The Great Gatsby" 
1

我相信一个模块比这里的类更合适,因为不需要“我标题中的事物“ - 您以字符串开头并以字符串结尾。如果标题有更多的方法,可能需要一个类。这是我的实施:

你失踪的作品是Array#map。一般来说,从基础ruby类(Array,String,Hash等)学习尽可能多的方法总是一个很好的投资。

module Title 
    DEFAULT_NON_CAPITALIZED_WORDS = %w{a an the and but for on at to or} 

    def self.titleize(str, nocaps = DEFAULT_NON_CAPITALIZED_WORDS) 
    str = str.downcase.split.map{|w| nocaps.include?(w) ? w : w.capitalize}.join(' ') 
    str[0].capitalize + str[1..-1] 
    end 
end 

测试:

puts Title.titleize("the great gatsby") 
puts Title.titleize("liTTle reD Riding hOOD") 
puts Title.titleize("The sword And The stone") 
puts Title.titleize("THE SWORD AND THE STONE") 

编辑:它可以在一个长的线来完成,但它需要一个正则表达式来进行初始资本:

str.downcase.split.map{|w| nocaps.include?(w) ? w : w.capitalize}.join(' ').sub(/^./, &:upcase) 
1

既然你的一部分希望输出为字符串,模块方法可能更合适。以下模块允许轻松扩展,并且相对清晰。

它看起来像这样:

module Title 
    SMALL_WORDS = %w(a an the at by for in of on to up and as but it or nor) 

    def self.titleize(str) 
    # Return the original string if it is empty 
    return str if str.match(/\A\w*\Z) 

    # Split the name into an array of words 
    words = name.split(' ') 

    # Capitalize every word that is not a small word 
    words.each do |word| 
     word[0] = word[0].upcase unless SMALL_WORDS.include? word.downcase 
    end 

    # Capitalize the first and last words 
    words.each_with_index do |word, index| 
     if index == 0 || index == words.count - 1 
     word[0] = word[0].upcase 
     end 
    end 

    # Return the words as a string 
    words.join(' ') 
    end 
end 

而且它的工作原理是这样的:

Title.titleize('the USA swimming association') 
    # => 'The USA Swimming Association' 
Title.titleize('the great charter of the liberties of england') 
    # => 'The Great Charter of the Liberties of England' 
Title.titleize(' a  history of of ') 
    # => 'A History of Of' 

有几个边缘的情况下创造了很好的titleize功能时,需要考虑:

  • 的无论如何,最后一个单词都应该大写(即使它是一个像“of”的单词)
  • 缩略词(如“美国”)应予以保留
0

我们需要使用each_with_index和if语句。请注意我是如何确保他们忽略第一篇使用索引> 0的文章。祝你好运!

class Title 
    attr_accessor :string 
    Articles = %w(an the of a and) 

    def initialize(string) 
    @string = string 
    end 

    def fix 
    fixed_words = [] 
    @string.downcase.split.each_with_index do |word, index| 
     if index > 0 && Articles.include?(word) 
     fixed_words << word 
     else 
     fixed_words << word.capitalize 
     end 
    end 
    fixed_words.join(" ") 
    end 
end 

p Title.new("the great gatsby").fix 
p Title.new("liTTle reD Riding hOOD").fix 
p Title.new("The lord of the rings").fix 
p Title.new("The sword And The stone").fix 
p Title.new("the portrait of a lady").fix 
p Title.new("THE SWORD AND THE STONE").fix 
相关问题