2015-01-20 63 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 
相關問題